Questionnaire design

Welcome to the questionnaire design guide!

An aim of this course is to develop your ability to translate business problems into actionable research questions and to design an adequate research plan to answer these questions. Therefore, you need to be equiped with knowledge on how to create a survey and properly conduct a research.

Generally, what you can expect from the survey design is similar to what one experiences in a relationship. If you try to take more than you commit, it doesn’t work out. Now on a serious note, if you follow guidelines mentioned here, you will certainly avoid usual traps your fellow collegues were caught in.

In a research process, conducting a survey is a part of (primary) data collection. Before we collect data, we have to make sure that preceding steps are correctly done. However, in the following sections we will focus on the process of designing a questionnaire. Eventually, you will be able to collect relevant data and apply appropriate statistical tests.

Questionnaire design process

A structured questionnaire is a research instrument designed to elicit specific information from a sample of a target population. Usually it is used in a standardized way with fixed-alternative questions (same questions and response options for all respondents).

An objective of a questionnaire is threefold:

  • to translate the information need into a set of specific questions that the respondent can and will answer,
  • to motivate, and encourage respondents to become involved, to cooperate, and to complete the questionnaire,
  • to minimize response error.

In order to meet these objectives, a questionnaire design process suggests the following sequence of steps:

Specification of the information needed

The questionnaire design should be aligned with the research design! In order to do make it aligned, it is necessary to review components of the problem and the approach. In particular, you should review the research questions, hypotheses and characteristics that influence the research design.

If you are interested in the causal effect of one particular (independent) variable on another (dependent) variable, think about an experimental design that might allow you to manipulate this variable. In this case, you particularly have to decide on the following:

  • Which variable to manipulate?
  • Whether to use a between-subjects or within-subjects design?
  • The cause-effect sequence (the cause must occur before the effect)
  • The number of experimental conditions
  • Potential interactions and relationships with other variables (does the effect depend on another variable?)

What you need to be careful about is the effect of reversed causation. The effect refers to the situation where the causal relationship could possible have an opposite direction from what we assumed at the first place. For instance, it is often assumed that an increase in individual income leads to increase in well-being (happiness). However, some researches suggest that this causation could have an opposite direction, i.e. that actually increase in well-being of an individual leads to an increase in income.

Here are some examples of causal research design applications:

  • To assess how a product’s country-of-origin impacts attractiveness across different countries.
  • To analyse the effects of rebranding on customer loyalty.

If you would like to analyze the effects of multiple categorical or continuous (independent) variables on one continuous (dependent) variable, you might use a regression model. When doing this, you particularly have to decide on:

  • How to measure the dependent variable (DV). This is particularly important, since you need a variable that is powerful in uncovering variation between subjects (e.g., open-ended questions, such as “How much are you willing to pay for this product” are good candidates). Moreover, you also need to consider the nature of your DV,i.e. whether it is an interval variable, ordinal or categorical variable. The nature of your DV will heavily influence your choice of a correct statistical test.

  • How to measure the independent variables (IV) (single-item vs. multi-item scales, categorical vs. continuous). Bear in mind that the nature of the IV, together with DV, affects your choice of a statistical test as well.

  • What other variables might cause the effect that you would like to investigate (to prevent omitted variable bias, i.e. variables that are not part of your model but still influence the dependent variable).

  • Potential interactions (e.g., is the effect of variable X stronger for group A vs. B?)

Specify the interviewing method

In the next step you should review the type of interviewing method you will use. At this point you need to think in which setting you aim to conduct your survery. For instance, should you do it in a face-to-face setting or rather online. Here you can find some advantages and disadvantages of online surveys:

Additionally, here is the list of the online tools you can use to conduct an online survey (usually for free):

Determine the content of questions

In this step you are starting to work on the content of you questions. There are several questions you should ask yourself when writing questions:

  • Is the question necessary?
  • Will I obtain the needed information?
  • Are several questions needed instead of one?
  • What type of data can I collect by asking that question (categorical or continuious)?

In your survey try to avoid asking double-barrelled questions.Those are a single question that attempts to cover two issues. Such questions can be confusing to respondents and result in ambiguous responses. Instead, you might ask multiple questions in order to obtain the inteded information.

Incorrect:
Do you think Nike Town offers better variety and prices than other Nike stores?

Correct:
Do you think Nike Town offers better variety than other Nike stores?
Do you think Nike Town offers better prices than other Nike stores?

Inability and unwillingness to answer

The quality of collected data you highly depends on your ability to address correct participants. Therefore, you need to make sure that your respondents are able to meaningfully answer your questions.

Examples:

  • Not every household member might be informed about monthly expenses for groceries purchases if someone else makes these purchases.
  • Use filter questions that measure familiarity and product use.
  • Include a “don’t know” option.
  • If you ask participants for monteray values (e.g. how much are you ready to pay for the XY product?) across several EU, make sure you indicate correct currency (e.g. HRK for Croatia or HUF for Hungary).
  • Think about how mobile friendly is the layout of your survey (if it is an online survey).
  • Good case practices suggest that there should not be more than 2 questions per page (for online surveys displayed on mobile phones).

If you are asking participants to recall certain brands for instance, make sure you use unaided recall question:

Example of unaided recall question:
What brands of soft drinks do you remember being advertised on TV last night?
Example of aided recall question:
Which of these brands were advertised last night on TV?
a) Coca-Cola
b) Pepsi
c) Red Bull
d) Evian
e) Don’t know

If you are asking participants to list something, the good case practice is to minimize the effort required by respondents:

Incorrect:
Please list all the departments from which you purchased merchandise on your most recent shopping trip to department store X.
Correct:
Please check all the departments from which you purchased merchandise on your most recent shopping trip to a department store:
a) Women’s dresses
b) Men’s apparel
c) Children’s apparel
d) Cosmetics
e) Jewelry
f) Other (please specify) ___________

In a case you are asking for information that could be considered sensitive (e.g. money, family life, political beliefs, religion), they should come at the end of the questionnaire. Moreover, it is recommendable to provide response categories rather than asking for specific figures:

Incorrect:
What is your household’s exact annual income?
Correct:
Which one of the following categories best describes your household’s annual gross income?
a) under 25.001 €
b) 25.001€ to 50.000 €
c) 50.001€ to 75.000 €
d) 75.001€ to 100.000 €
e) over 100.000 €

Decide on measurement scales and scaling techniques

Every statistical analysis requires that variables have a specific levels of measurement. Measurement scales you choose for your questions in a survey will affect the answers you get and eventually statistical test you can apply. For instance, it would not make sense to compute an average of genders. An average of a categorical variable does not make much sense. Moreover, if you tried to compute the average of genders defined in numeric values (e.g. male=0, female=1), the output would be interpretable.

Therefore, it is crucial to become familiar with possibilities of each scale before you choose to add another question to your survey. Consequently, chances to obtain data you did not intend to collect and chances that you will not be able to apply tests you intended are significantly lower.

In the following table you can get a quick overview of possibilities per each measurement scale. :

In the table below you can find general procedure for choosing a correct analysis based on the measurement scale of your data and number of variables. It shows statistical analyses we covered during the course and aims to help you choose among them based on the nature of dependent variables on the side, and the nature and the number of your independent variables on the other side:

When it comes to scaling techniques, they are meant to study the relationship between objects. The basic scaling techniques classification is on comparative and non-comparative scales.

The noncomparative scale each object is scaled independently of the other objects. The resulting data is supposed to be measured in an interval and ratio scaled.

Comparative scales (or nonmetric scaling) compare direclty the stimulus object. For example, the respondent might be asked directly about his preference between domestic and foreign beer brands. As a result, the comparative data collected can only be interpreted in relative terms. In the following sections we will walk through both types of comparative scales and briefly introduce them.

Comparative scale: Paired Comparison

  • Respondent is presented with two objects and asked to select one according to some criterion.
  • The nature of resulting data is ordinal
  • Assumption of transitivity (if X > Y and Y > Z, then X > Z) enables the paired comparison data to be converted into a rank order. To do so, you need to indetify the number of times the object is preferred by adding up all the matrices.
  • Effective when the number of objects is limited as it requires the direct comparison, and a bigger number of objects makes the comparison becomes unmanagable.
  • Example:
    For each pair, please indicate which of the two brands of beer in the pair you prefer.

Comparative scale: Rank Order

  • Allow a certain set of brands or products to be simultaneously ranked based upon a specific attribute or characteristic.
  • The rank order scaling is a good proxy for to the shopping setting as there are simultanious comparisons of objects.
  • The rank order scaling results in the data of ordinal nature.
  • Example:
    Rank the various brands of beer in order of preference. Begin by picking out the one brand that you like most and assign it a number 1. Then find the second most preferred brand and assign it a number 2. Continue this procedure until you have ranked all the brands of beer in order of preference. No two brands should received the same rank number.

Comparative scale: Constant sum

  • Respondents allocate a constant sum of units (e.g., points, dollars) among a set of stimulus objects with respect to some criterion.
  • Constant sum is similar to rank order, but it carries specific units.
  • The resulting data does not just indicate important factors, but also by how much a factor supersedes another one.
  • Constant sum scaling can be used to observe the comparative significance respondents assigned to various factors of a subject.
  • Example:
    There are 8 attributes of bottled beers. Please allocate 100 points among the attributes so that your allocation reflects the relative importance you attach to each attribute.

  • Basic analysis of constant-sum data involves tabulation of responses and presenting them as either quantities (e.g., “on average, 7 points were allocated to”high alcohol level“), or, as proportions (”On average, 7% of points were allocated to “high alcohol level”).

Non-Comparative Scales: Continuous Rating Scales

  • Participants rate the objects by placing a mark at the appropriate position on a line that runs from one extreme of the criterion variable to the other.
  • One of the advantages of the continuous rating scale is that it is easy to administer.

  • Once the ratings are collected, you can splits up the obtained ratings into categories and then assign those depending on the category in which the ratings fall.

Non-Comparative Scales: Itemized Rating Scales

  • The respondents are provided with a scale that has a number or brief description associated with each category.
  • The categories are ordered in terms of scale position, and the respondents are required to select the specified category that best describes the object being rated.
  • The commonly used itemized rating scales are the Likert, semantic differential and Stapel scales.
Itemized Rating Scales: Likert scale
  • Requires respondents to indicate their attitude towards the given object through the degree of agreement or disagreement with each of a series of statements within typically five or seven categories.
  • Reversed code of some items increases validity.
  • One limitation is time required to answer a question on a Likert scale. Compared to other itemized scaling techniques, Likert scale is more time consuming as each respondent is required to read every statement given in a questionnaire before assigning a numerical value to it.

In the table below you can find a couple of commonly measured constructs in marketing research such as attitude, importance, purchase intention and similar.

Itemized Rating Scales: Semantic Differential
  • Typically, participants rate objects on a number of itemized, seven-point rating scales bounded at each end by one of two bipolar adjectives.

  • Semantic differential can measure respondent attitudes towards something (products,concepts, items, people…).

  • It helps you find the repondent’s position is on a scale between two bipolar adjectives such as “Sweet-Sour” or “Bright-Dark”. In comparison to Likert scale, which uses generic scales (e.g. extremely dissatisfied to extremely satisfied), semantic differential questions are posed within the context of evaluating attitudes.

  • Widely used rating scale in marketing research due to its versatility

When creating a semantical difference question, you should consider the following:

  • Number of categories:

  • Balanced vs. unbalanced:

  • Odd/even number of categories:

  • Forced vs. non-forced response

  • Verbal description:

Questionnaire structure

The sequnece of questions in a questionnaire could play imporant role. For instance, more sensitive questions (such as demographic-related questions) are usually placed at the end as they can trigger change in respondent’s behavior.

If you plan to conduct an online survey, then you need to think about the respondent’s experience while doing your questionnaire. For instance, spread the content over more short pages and do not have fewer long pages. In online surveys, two questions on one page is a useful rule of thumb. Generally, respondents are reluctant to read and fill out long questionnaire pages. Hence, long pages will lead to a higher dropout rate. In order to reduce dropout rate state how long the survey will approximately take in the introduction of the questionnaire. Take into account that tools like Qualtrics provide the estimated response time in the survey overview.

Consider that the most of people usually use their phones to fill it out. Think about how the questionnaire will appear on a phone screen too. In that regard, think of length of questions especially.

In the end, the questionnaire structure has to be aligned with the research design. For example, if your research design features an experiment, this needs to be reflected in the questionnaire (e.g., you need to assign the respondents randomly to the experimental conditions in case of a between-subjects comparison).

Questionnaire structure for a between-subjects design

In a between-subject design you randomly assign each respondent to different experimental conditions. They would then complete tasks only in the condition to which they are assigned.

For instance, we would like to test the effect of two advertisements on purchase intention. Therefore, one group of (randomly assigned) respondents will be exposed to one advertisement version while the other group (of randomly assigned respondents) will be exposed to another version. After that, both groups of respondents should express their willingness to buy the advertised product. Evenutally, if the dependent variable (e.g. willingness to buy) is measured on interval or ratio scale, then you can use independent t-test to compare group means. The whole experimental design should be organised as following:

Questionnaire structure for a within-subjects design

This type of experimental design involves exposing each respondent to all of the user experimental conditions you’re testing. This way, each respondent will test all of the conditions.

For instance, we would like to test again the effect of two advertisements on purchase intentions, but this time in a within-subject design. First, each respondent will be exposed to the first version of advertisement and right after that asked to rate his/her willingness to buy the advertised product. Subsequently, each participant will be shown another version of advertisement and again rate his/her willingness to purchase the advertised product. Finally, we can compare group means with paired sample t-test (given that data is measured on interval or ratio scale).

Question wording

Generally, question wording should enable each respondent to understand questions and to be able to answer them with reliability. Reliability means that, if a respondent was asked the same question again, he/she would give the same answer again. A number of common problems regarding the question wording have been identified, so we will address the most important ones.

In order to ensure reliability, the issue in terms of who, what, when and where should be defined in each question.
Example: Which brand of shampoo do you use?
Who (the respondent): It is not clear whether this question relates to the individual respondent or the respondent’s total household.
What (the brand of shampoo): It is unclear how the respondent is to answer this question if more than one brand is used.
When (unclear): The time frame is not specified in this question. The respondent could interpret it as meaning the shampoo used this morning, this week, or over the past year.
Where (not specified): At home, at the gym? Where?

A more clearly defined question is:
Which brand or brands of shampoo have you personally used at home during the last month? In the case of more than one brand, please list all the brands that apply.

Use ordinary words. Words should match the vocabulary level of the participants.
Incorrect:
“Do you think the distribution of soft drinks is adequate?”
Correct:
“Do you think soft drinks are easily available when you want to buy them?”

Avoid double negative form. Double negative question forms can confuse respondents, especially when they need to answer with “Agree” or “Disagree”.

Incorrect:
Do you think that it is not uncommon that boys play basketball?
Correct:
In your opinion, is it common that boys play basketball?

Avoid leading questions.Leading questions clue the participant to what the answer should be. Such questions introduce a bias in a particular direction.
Incorrect:
“Is Colgate your favorite toothpaste?”
Correct:
“What is your favorite brand of toothpaste?”

Avoid ambiguous words. Words such as usually, normally, frequently, often, regularly, and other similar words, do not define frequency clearly enough.

Incorrect:
“In a typically month, how often do you go to a movie theater to see a movie?”
a) Never
b) Occasionally
c) Sometimes
d) Often
e) Regularly

Correct:
“In a typically month, how often do you go to a movie theater to see a movie?”
a) Less than once
b) 1 or 2 times
c) 3 or 4 times
d) More than 4 times

Choose adequate order

One of the last steps in a process of designing a questionnaire is choosing adequate order of questions and instructions for respondents.

At the begining, you should provide a short and easy-to-understand introduction to the topic. Use simple language and avoid technical terms (e.g., not many people will know the terms “manufacturer brand” and “store brand”). Additionally, in the introduction you should state how long the survey will approximately take.

The opening questions should be interesting, simple and non-threatening. They are crucial because it is the respondent’s first exposure to the questionnaire and is likely to set the tone for the rest of questions in the questionnaire. If too difficult to understand, or sensitive in some way, respondents are likely to stop answering your questions. Qualifying questions (or screening questions) should serve as the opening questions (if applicable). Their purpose is to identify a potential respondent that is eligable to proceed with the research survey.

After the opening part, you should establish an optimal question flow. General questions should precede the specific questions. Questions on one subject, or one particular aspect of a subject, should be grouped together. It may feel confusing to be asked to return to some subject they thought they already gave their opinions about.

As respondents are moving towards the end of the questionnaire, they are likely to become increasingly indifferent and might give careless answers. Therefore, questions of special importance should ideally be included in the earlier part of the questionnaire.

Finally, you should pay particular attention to provide all prescribed definitions and explanations before you ask a question. This ensures that the questions are undestood in consistent way by every respondent.

Test your questionnaire

Finally, before you distribute the final questionnaire, there are some things to consider. First, you should always pretest your questionnaire before sharing it! Test all aspects of the questionnaire (content, wording, sequence, form & layout, etc.). If possible, use respondents in the pretest that are similar to those who will be included in the actual survey. Ideally, the pretest sample size should be small (in a real scenario this could varyfrom 15 to 30 respondents; for the group project, a lower number will be sufficient). After each significant revision of the questionnaire, conduct another pretest, using a different sample of respondents. Eventually, code and analyze the responses obtained from the pretest so that you make sure that you collected information you intended to collect.

After testing your questionnaire you should be able to determine whether:

  • The questions are properly framed
  • The questions wording triggers any biases
  • The questions are placed in the optimal order
  • The questions are understandable
  • Specifying questions are needed or some need to be eliminated

Questionnaire in Qualtrics

A questionnaire creation in Qualtrics starts with creation of a Qulatrics project. Each project consists of a survey, distribution record, and collection of responses and reports. There are three ways to create a questionnaire.First, you can create a new survey project from scratch. Second, you can create a new questionnaire from a copy of an existing questionnaire. Eventually, you can create from a template in your Survey Library, or from an exported QSF file.

In order to create a completely new questionnaire, you need to do the following:

Go to the Projects page by clicking the Qualtric XM logo or clicking Projects on the top-right.

Create new project by clicking the blue button on the right side.
In the “Create your own” section click on the survey button.

Enter a name for your survey and get started with a survey creation.

If you would like to create a new questionnaire on a basis of an already existing one, then you choose “From a Copy”. Subseqeuntly, you need to indicate the questionnaire you would like to copy. Now you are good to go!

If there is a questionnaire in the Qualtrics Library you would like to use, then you need to choose “From Library”, and indicate one library name in the dropdown menu.

Question types and data analysis

Attaching package: 㤼㸱janitor㤼㸲

The following objects are masked from 㤼㸱package:stats㤼㸲:

chisq.test, fisher.test

Parsed with column specification: cols( .default = col_double(), StartDate = col_character(), EndDate = col_character(), IPAddress = col_logical(), RecordedDate = col_character(), ResponseId = col_character(), RecipientLastName = col_logical(), RecipientFirstName = col_logical(), RecipientEmail = col_logical(), ExternalReference = col_logical(), LocationLatitude = col_character(), LocationLongitude = col_character(), DistributionChannel = col_character(), UserLanguage = col_character(), Q7_MC_sa_country_3_TEXT = col_logical(), Q23_Gender_3_TEXT = col_logical(), Condition = col_character() ) See spec(…) for full column specifications.

[1] 117 54 [1] 2 2 2 2 2 1 2 1 1 1 2 1 2 1 1 1 2 2 2 2 2 1 1 1 1 2 1 2 1 1 1 2 2 1 2 [36] 2 2 2 2 2 1 2 1 2 1 1 1 1 2 2 2 1 2 2 2 2 1 2 1 2 2 2 1 1 2 2 2 1 2 2 [71] 2 1 2 1 2 1 1 2 2 1 1 2 2 2 1 2 1 1 2 2 2 1 2 2 2 1 2 1 1 2 1 2 1 2 2 [106] 1 2 2 1 2 1 1 2 2 2 1 2 attr(,“label”) Q23_Gender " Selected Choice" [1] 2 2 1 1 1 1 2 2 2 2 2 2 2 1 2 2 1 2 2 2 2 2 2 1 1 1 2 2 2 2 1 2 2 1 2 [36] 2 1 2 2 1 2 1 2 2 1 2 2 1 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2 2 1 2 2 1 2 [71] 2 2 1 2 2 1 2 2 1 2 2 1 2 1 1 2 2 2 2 2 2 1 2 1 1 1 2 2 2 2 2 2 2 2 2 [106] 2 1 1 1 2 1 2 2 2 2 2 2 attr(,“label”) Q7_MC_sa_country " Selected Choice"

In this chapter we will encounter the nature of data you collect when conducting a survey. It will help you choose a type of a question depending on the nature of data you want to collect and on the type of statistical tests you want to apply.

Here you can find an example of a questionnaire in Qualtrics with guidelines and suggestions related to each question type.

Multiple choice with a single answer

Multiple Choice with a single answer is a type of closed-ended question that lets respondents select one answer from a defined list of choices.

Type of data you obtain is categorical, and the output comes in the following form:

Multiple Choice Question with Single Answer
In a typical week, how many hours do you spend watching movies or TV series on Netflix?
3
4
5
4
5
2

Data handling

What to do with this data now? First, we need to load it in R and prepare for analysis. The numbers you see in the output R recognizes as numeric. In order to conduct statistical modelling and properly visualize our results, we need to convert our data to a factor class.

A factor (or coding variable) represents different groups of data by using numbers (integers). In fact, factors appear as numeric variables, but they hold meaning of labels/names of data groups, i.e. nominal variable. These data groups are represented in a form of ‘levels’.
In our case, our multiple choice question output will contain 4 data groups (‘Grocery Store’, ‘Online shop’, ‘Specialised coffee shop’, ‘other’) after converting it to factor:

# Convert numeric value to factors
qualtrics$'In a typical week, how many hours do you spend watching movies or TV series on Netflix?' <- factor(qualtrics$'In a typical week, how many hours do you spend watching movies or TV series on Netflix?', levels = c(1:5), labels = c('Never','1-2 hours','3-4 hours','5-6 hours','more than 6 hours'))

qualtrics$` Selected Choice_1` <- factor(qualtrics$` Selected Choice_1`,levels = c(1:2),labels = c("Male","Female"))

qualtrics$` Selected Choice` <- factor(qualtrics$` Selected Choice`, levels = c(1:2), labels=c("Austria","Germany"))


# Table
table(qualtrics$'In a typical week, how many hours do you spend watching movies or TV series on Netflix?')

            Never         1-2 hours         3-4 hours         5-6 hours 
               19                18                22                35 
more than 6 hours 
               23 
table(qualtrics$` Selected Choice`)     #countries

Austria Germany 
     35      82 
table(qualtrics$` Selected Choice_1`)   #gender

  Male Female 
    49     68 

Visualisation

Second, you might want to visualize your results. In order to do so, the data format needs to be in the appropriate format.Here we proceed with data fromat adaptation from the point where we stopped:

# Converting long format to the visualisation-friendly format
mlc_visualisation <- as.data.frame(table(qualtrics$'In a typical week, how many hours do you spend watching movies or TV series on Netflix?'))

# Naming columns
names(mlc_visualisation) <- c('Time','Count')

# Observing
mlc_visualisation
NA

The simpliest way to visualize data obtained from multiple choice question with a single answer is a bar chart:

## Basic bar chart
labels <- as.character(mlc_visualisation$Time) #Save labels for x-axis in the barplot
barplot(mlc_visualisation$Count, # Column to visualize
        xlab='Time', # X-axis label
        ylab = 'Count(answers)', # Y-axis label
        names.arg = labels,
        main = 'How many hours do you spend watching movies or series on Netflix?') # Title

R package ggplot2 allows you to create visually appealing graphs:

## ggplot2 bar chart
library(ggplot2)
p <- ggplot(data=mlc_visualisation, 
             aes(x=Time, y=Count, fill=Time)) +
             geom_bar(stat='identity') + theme_minimal() + labs(title = "In a typical week, how many hours do you spend watching movies or series on Netflix?")
p

Another R library which can help you make amazing interactive charts in a minute is plotly. Here we use a function called ggplotly(), which allows you to turn any ggplot2 chart interactive. Since we have already created a bar chart using ggplot2 and saved it as “p”, we will just turn it into plotly graph:

## ggplotly bar chart

library(plotly)
ggplotly(p)

An improved version of ggplot2 package is the packaged called ggvis, which is still in developing:

## ggvis bar chart

library(ggvis)
ggvis(mlc_visualisation, 
      x = ~Time, 
      y = ~Count, 
      fill=~Time)

Statistical analysis

Data type collected from the previous question is ordinal as we are able to make a natural order of the levels. Since it is ordinal data type, it belongs to categorical data. For the analysis of categorical data we can use Chi-square test or Fisher’s test if a count for some level is less than 5.

Fischer’s exact
Fisher’s exact test is used to test a hypothesis with data obtained from multiple choice questions with single answer. Results from multiple choice questions with multiple answers are treated with different test.
  • Application: when you have 1 dependent variable and 1 independent variable with 2 or more levels/factors
  • Used when frequency in at least one cell is less than 5 . When frequencies in each cell are greater than 5, Chi-square test should be used.
  • Hypothesis: Is there a significant difference in frequencies between values observed in cells and values expected in cells ? (R for Marketing and Research Analytics)
  • H0: There is no relationship between the two categorical variables.Therefore, two categorical variables are independent. Knowing the value of one variable does not help to predict the value of the other variable.
  • H1: There is a relationship between the two categorical variables.Therefore, two categorical variables are dependent.Knowing the value of one variable helps to predict the value of the other variable.
  • Usually, this type of test is used on 2x2 contingency tables. However, it can be applicable on contingency tables of larger dimensions.

Example: We would like to know whether a number of hours spent watching Netflix depends on the respondents’ country of origin.

# Creation of contingency table
fisher_test_table <-table(qualtrics$` Selected Choice`,qualtrics$'In a typical week, how many hours do you spend watching movies or TV series on Netflix?')
# Check how our contigency table looks like
fisher_test_table
         
          Never 1-2 hours 3-4 hours 5-6 hours more than 6 hours
  Austria     3         7         6        11                 8
  Germany    16        11        16        24                15
# Since we have a count less than 5, we should apply Fisher's test instead of Chi-square.

# Fisher's test
test <- fisher.test(fisher_test_table)
test

    Fisher's Exact Test for Count Data

data:  fisher_test_table
p-value = 0.575
alternative hypothesis: two.sided
# p-value
test$p.value
[1] 0.5750401

From the output and from test$p.value we see that the p-value is higher than the significance level of 5%. Like any other statistical test, if the p-value is higher than the significance level, we can not reject the null hypothesis.

In our case, not rejecting the null hypothesis for the Fisher’s exact test of independence means that there is no significant relationship between the two categorical variables. Therefore, knowing the value of one variable does not help to predict the value of the other variable.

Chi-square test: Goodness of fit & Independence test
  1. Goodness of fit
    • Application: when you only have 1 dependent variable and none independent variables
    • Hypothesis: Is there a significant difference in frequencies between values observed in cells and values expected in cells ? (R for Marketing and Research Analytics)
    • H0: There is no significant difference between the observed and the expected frequencies.
    • H1: There is a significant difference between the observed and the expected frequencies.
    • If we don’t specify expected frequency per cell (see in the code below), then it is expected that all cells show an eqaul frequency.
    • Example :‘Do the numbers of respondents who are spending different amount of hours watching Netflix significantly differ from each other?
  • Note that we did not assume any specific distribution, so we are assuming that each count will have the same or similar number.
    • # Creating table 
      (mlc_chi_square <- table(qualtrics$'In a typical week, how many hours do you spend watching movies or TV series on Netflix?'))
      
                  Never         1-2 hours         3-4 hours         5-6 hours 
                     19                18                22                35 
      more than 6 hours 
                     23 
            
      # Chi-square test (without given expected values = equal values )
      chisq.test(mlc_chi_square)
      
          Chi-squared test for given probabilities
      
      data:  mlc_chi_square
      X-squared = 7.9145, df = 4, p-value = 0.09476

      The p-value of the test is higher than 0.05. We can conclude that the numbers of respondents who spent different amount of hours watching Netflix are commonly distributed. Observed distribution does not differ significantly from the expected. This result does not surprise if you take a look at the values for each level in the table we created before conducting the test. There you can see that count of answers in each level is more or less not deviating too much. It is visible if you take a look at the previous visualisations as well.

      If we are interested in testing more specific distribution, i.e. expect that 40% of our respondents are watching Netflix 3-4 hours, we can introduce corresponding distribution in the test.

      # Expected values in percentages for each alternative. The sum must be 1.
      expected_values <- c(0.10, # We expect that 10% of our respondents do not watch Netflix at all ("Never").
                           0.20, # We expect that 20% of our respondents watch Netflix 1-2 hours a week.  
                           0.40, # We expect that 40% of our respondents watch Netflix 3-4 hours a week.
                           0.20, # We expect that 20% of our respondents watch Netflix 5-6 hours a week.
                           0.10 # We expect that 10% of our respondents watch Netflix more than 6 hours a week.
                          )
      # Chi-square test with expected values
      chisq.test(mlc_chi_square, p=expected_values)
      
          Chi-squared test for given probabilities
      
      data:  mlc_chi_square
      X-squared = 35.607, df = 4, p-value = 3.486e-07

      This time the p-value of the test is lower than 0.05.We have an evidance that observed distribution does significantly differ from the expected distribution (10%/20%/40%/20%/10%).

      1. Chi-Square Test of Independence
        • Application: when you have 1 dependent variable and 1 independent variable with 2 or more levels/factors
        • Hypothesis: Is there an association between categorical variable X and categorical variable Y?
        • H0: There is no association between the two variables.
        • H1: There is an association between the two variables.
        • Example: Is there an association between gender and the hours spent watching Neflix during a week?
# Creation of contingency table
chi_square_table <-table(qualtrics$` Selected Choice_1`,qualtrics$'In a typical week, how many hours do you spend watching movies or TV series on Netflix?')

# Chi-square independence test
chisq.test(chi_square_table)

    Pearson's Chi-squared test

data:  chi_square_table
X-squared = 1.5739, df = 4, p-value = 0.8135

Since the p-value (0.8135) is higher than the significance level (0.05), we cannot reject the null hypothesis. Thus, we conclude that there is no association relationship between gender and number of hours spent watching Netflix. Therefore, we can say that the hours spent is independent from the gender of participant.

Multiple choice with multiple answers

Before we conduct any test, we will do some simple calculatios and visualise our data.

# Rename columns
colnames(qualtrics)[38] <- "ja!Naturlich"
colnames(qualtrics)[39] <- "Clever"
colnames(qualtrics)[40] <- "Spar Vital"
colnames(qualtrics)[41] <- "..."

# Replacing NA with 0
qualtrics$`ja!Naturlich`[is.na(qualtrics$`ja!Naturlich`)]=0
qualtrics$Clever[is.na(qualtrics$Clever)]=0
qualtrics$`Spar Vital`[is.na(qualtrics$`Spar Vital`)]=0
qualtrics$...[is.na(qualtrics$...)]=0

# Calculating frequency, percentage of respondents and percentage of cases
df.cochran <- data.frame(Frequnecy = colSums(qualtrics[38:41]),
                         Share_of_respondents = (colSums(qualtrics[38:41])/sum(qualtrics[38:41]))*100,
                                Share_of_cases =((colSums(qualtrics[38:41]))/nrow(qualtrics[38:41]))*100)
# Observing
df.cochran

# Visualisation
barplot(df.cochran[,3], names.arg = row.names(df.cochran), main = "% of Respondents familiar with brands", xlab = "Brand",ylab = "Percentage")

The visualisation above depicts the fact that more than 60% percent of people are familiar with the brand “ja!Naturlich”, while we can not say the same for other brands considered in our question.

For the analysis of results collected with multiple choice question with multiple possible answers, we can use Cochran’s Q test.Although we did not mention it before, it is not too different from what you have already learned about other tests.

The Cochran’s Q test and associated multiple comparisons require the following assumptions: 1. Responses are dichotomous and from k number of matched samples. 2. The subjects are independent of one another and were selected at random from a larger population. 3. The sample size is sufficiently “large”. (As a rule of thumb, the number of subjects for which the responses are not all 0’s or 1’s, n, should be ≥ 4 and nk should be ≥ 24)

In a within-subjects experiment design with three or more observations of a dichotomous(= just two levels such as “Yes” or “No”) categorical outcome, you utilize Cochran’s Q test to assess main effects.Similarly, in our multiple choice question with multiple answers we have the same respondent going through three or more potential answers with dichotomous(=yes or no) categorical outcome.

library(nonpar)

# Creation of matrix
matrix.cochran <- cbind(qualtrics$`ja!Naturlich`,
                   qualtrics$Clever,
                   qualtrics$`Spar Vital`,
                   qualtrics$...)
# Turning NAs to 0
matrix.cochran[is.na(matrix.cochran)]=0

# Cochran test                   
cochrans.q(matrix.cochran, alpha = 0.05)

 Cochran's Q Test 
 
 H0: There is no difference in the effectiveness of treatments. 
 HA: There is a difference in the effectiveness of treatments. 
 
 Q = 25.5681818181818 
 
 Degrees of Freedom = 3 
 
 Significance Level = 0.05 
 The p-value is  1.17439848891232e-05 
 There is enough evidence to conclude that the effectiveness of at least two treatments differ. 
 

The p-value less than 0.05 indicates that there is enough evidence to conclude that some of the store brands are better known among our respondents than other. In order to take a closer look at it, we need to conduct a post hoc test.

library(DescTools)
list.cochran <- list(qualtrics$`ja!Naturlich`,
                   qualtrics$Clever,
                   qualtrics$`Spar Vital`,
                   qualtrics$...)

# Replacing NAs in the list with 0 in order to be able to run the test
list.cochran <- rapply(list.cochran, f=function(x) ifelse(is.na(x),0,x), how="replace" )

# Post hoc test (Dunn Test)
DunnTest(list.cochran, method="bonferroni")

 Dunn's test of multiple comparisons using rank sums : bonferroni  

    mean.rank.diff    pval    
2-1            -36  0.1093    
3-1            -18  1.0000    
4-1            -74 7.3e-06 ***
3-2             18  1.0000    
4-2            -38  0.0761 .  
4-3            -56  0.0014 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

From the results of the Dunn Test, we can see that there is a big difference between 1 (“ja!Natürlich”) and 4(“…”), as well as between 4(“…”) and 3(“Spar Vital”).

Rank order question

A rank order question asks respondents to compare items to each other by placing them in order of preference. Note that the data obtained from a rank order question shows an order of a respondent’s pereference, but not the difference between items. For instance, if the the most important feature of a fitness tracker for a respondendt XY is “Measuring steps” and the second most important feature “Calories burned”, we don’t know for how much more important is the former one in comparison to the latter one.

Intuitive question to ask is the following: which feature of the fitness tracker is the most important for our respondents?

We can answer this question by calculating a mean rank for each feature. Before we do so, we will create a separate data frame and add columns of the response data.

rank.data <- data.frame(qualtrics$` Measuring steps`,
                        qualtrics$` Calories burned`,
                        qualtrics$` Measuring heartbeat`,
                        qualtrics$` Exercise tracking`,
                        qualtrics$` Measuring distance`)
colnames(rank.data)<-c("Measuring steps","Calories burned","Measuring heartbeat","Exercise tracking","Measuring distance")

First information we would like to know is how many preference combinations there are, and how repetitive they are. We can obtain that information by creating a summary of the ranking data frame we created.

library(pmr)
Loading required package: stats4
test <- rankagg(rank.data)
test
                 n
 [1,] 2 1 3 4 5 10
 [2,] 1 3 2 4 5 19
 [3,] 2 3 1 4 5 17
 [4,] 1 2 4 3 5  4
 [5,] 4 2 1 3 5  3
 [6,] 3 2 1 5 4 15
 [7,] 1 3 5 2 4 10
 [8,] 1 2 4 5 3 10
 [9,] 2 4 1 5 3  9
[10,] 1 2 5 4 3  9
[11,] 5 4 3 1 2  3
[12,] 2 3 4 5 1  8

The matrix we received as an output is the summary of our ranking data. It shows that, for instance, the preference combination “2,1,3,4,5” repeats 10 times in the data frame. More specifically, it means that there are 10 respondents who prefer the item 2(“Calories burned”) the most, then the item 1(“Measuring steps”), and so on.

Now we can calculate the mean rank for each feature and conclude which feature is the most important to our respondents:

# Mean rank of each fitness tracker feature
destat(test)$mean.rank
Descriptive statistics of ranking data: 
$mean.rank: mean ranks; $pair: pairs; $mar: marginals
[1] 1.811966 2.581197 2.598291 4.051282 3.957265

As we can observe from the output, the item 1(“Measuring steps”) shows the best mean rank among all items. Therefore, we can assume that the “Measuring steps” is most important for our respondents. However, in order to statistically prove it and become sure that this is not just by mere chance, we can conduct Friedman rank sum test.

Friedman rank sum test is used to identify whether there are any statistically significant differences between the distributions of 3 or more paired groups. It is used when the normality assumptions for using one-way repeated measures ANOVA are not met. Another case when Friedman rank rum test is used is when the dependent variable is measured on an ordinal scale, as in our case.

Before we conduct the Friedman rank sum test, we will visualise our data:

# Preparing data frame for Friedman rank sum test
library(reshape2)
library(ggpubr)
library(rstatix)

Attaching package: 㤼㸱rstatix㤼㸲

The following object is masked from 㤼㸱package:janitor㤼㸲:

    make_clean_names

The following object is masked from 㤼㸱package:stats㤼㸲:

    filter
library(ggstatsplot)
In case you would like cite this package, cite it as:
     Patil, I. (2018). ggstatsplot: "ggplot2" Based Plots with Statistical Details. CRAN.
     Retrieved from https://cran.r-project.org/web/packages/ggstatsplot/index.html
rank.data.long <- melt(rank.data,value.name = "Rank",variable.name = "Feature")
No id variables; using all as measure variables
attributes are not identical across measure variables; they will be dropped
# We have just turned our data frame from the wide format to the long format by using function melt(). If we take a look at head and tail of our new data frame, we can see that it contains just two columns, "Rank" and "Feature".
tail(rank.data.long)
head(rank.data.long)

# Quick visualisation
p <- ggboxplot(rank.data.long, x = "Feature", y = "Rank", add = "jitter",title = "What features are important to you when evualting fitness trackers?")
ggplotly(p)


# Advanced visualisation
ggstatsplot::ggwithinstats(
  data = rank.data.long,
  x = Feature,
  y = Rank,
  type = "np",
  pairwise.comparisons = TRUE, # show pairwise comparison test results
  title = "What features are important to you when evualting fitness trackers?")

Already from the advanced visualisation, that includes Friedman rank sum test and pairwise comparison, we can have an insight in significance of differences among features.

# Friedman test 
friedman.test(as.matrix(rank.data))

    Friedman rank sum test

data:  as.matrix(rank.data)
Friedman chi-squared = 176.42, df = 4, p-value < 2.2e-16

Friedman rank sum test has a p-value lower than 0.05, so we can conclude that here are significant differences between at least two features (what we have already seen in our visualisation). Even though we have identified differences between preferences towards features in our advanced visualisation, we will conduct a post hoc test in order to demonstrate traditional way of calculating pairwise comparisons.

wilcox_test(Rank ~ Feature, paired = TRUE, p.adjust.method = "bonferroni", data = rank.data.long)

The output table provides us with p-values referring to significance of difference in mean ranks of each pair. For instance, the first 4 rows proves that the differences between the mean rank of the feature “Measuring steps” and each of the rest of features are significant. Consequently, we can conclude that this feature is by far the most important among our respondents.

Another question that may be interesting to explore is whether there are any complementary feautres ? Or features which overlap each other in its funcionality? In order to have a look at that, we can investigate the correlation between ranks assigned to each feature.

#Correlation Matrix
cor.matrix<-cor(rank.data, method=c('spearman'))
cor.matrix
                    Measuring steps Calories burned Measuring heartbeat
Measuring steps          1.00000000     -0.04651331          -0.6569094
Calories burned         -0.04651331      1.00000000          -0.2221626
Measuring heartbeat     -0.65690943     -0.22216264           1.0000000
Exercise tracking        0.29633223     -0.10838758          -0.3255840
Measuring distance      -0.05958032     -0.11694481          -0.3817895
                    Exercise tracking Measuring distance
Measuring steps             0.2963322        -0.05958032
Calories burned            -0.1083876        -0.11694481
Measuring heartbeat        -0.3255840        -0.38178948
Exercise tracking           1.0000000        -0.47176821
Measuring distance         -0.4717682         1.00000000

At the first glance we can observe a lot of negative values, meaning that many features correlate negatively relative to each other. In order to make the interpretation easier, we will try to visualise correlations in a form of a correlation matrix.

library(corrplot)
corrplot 0.84 loaded
corrplot(cor.matrix, method="color", type = "upper", order = "hclust")

From the correlation matrix we can confirm that almost all features negatively correlate to each other. An exception is the relationship between feature “Measuring steps” and “Exercise tracking”, which correlates positvely. This matrix can be useful for digging deeper in relationship between preferences for features. For instance, we can assume that feature “Measuring steps” and “Exercise tracking” correlate positively because users see them as complementary features. Moreover, if we say that walking is a type of exercise (in case of longer walking routes), we can assume that users, who ranked “Exercise tracking” high, ranked “Measuring steps” high as well, because they perceive it as another type of “Exercise tracking”.

Constant Sum question

If you wish to obtain information about how much one attribute is preferred over another one, you may use a constant sum scale. The total box should always be displayed at the bottom to make it easier for respondents.A constant sum question permits collection of ratio data type. With data obtained we would be able to express the relative importance of the options.

Constant Sum Question
Location Price Ambience Customer Service id
32 23 32 13 1
25 30 22 23 2
19 21 30 30 3
20 20 20 40 4
30 30 10 30 5
0 20 20 60 6

Data visualisation

# Compute descriptive statistics
library(pastecs) 
res <- stat.desc(constant.sum)
round(res[,1:4],2)
# Creation of the long version of data frame
constant.sum.long <-melt(constant.sum, variable.name ="Factor" ,value.name = "Points")
constant.sum.long
# Boxplot basic
constant.sum[,-5] %>%
boxplot(constant.sum.long$Points ~ constant.sum.long$Factor , col=rgb(0.3,0.5,0.4,0.6) , ylab="Points",xlab="", main= "What factors do you consider when choosing a place to go for a dinner?")


# Boxplot ggplot2
p<-constant.sum.long %>% 
  filter(Factor!="id") %>%
  ggplot(aes(x=Factor, y=Points, fill= Factor)) +
    geom_boxplot()  +
    theme_minimal() +
    ggtitle("What factors do you consider when choosing a place to go for a dinner?") +
    xlab("")
ggplotly(p)

With the data collected we are able to answer the question: what factor is the most important for our respondents when they go out for a dinner?

library(robCompositions)
Loading required package: pls

Attaching package: 㤼㸱pls㤼㸲

The following object is masked from 㤼㸱package:corrplot㤼㸲:

    corrplot

The following object is masked from 㤼㸱package:stats㤼㸲:

    loadings

Loading required package: data.table
data.table 1.13.0 using 2 threads (see ?getDTthreads).  Latest news: r-datatable.com

Attaching package: 㤼㸱data.table㤼㸲

The following objects are masked from 㤼㸱package:pastecs㤼㸲:

    first, last

The following objects are masked from 㤼㸱package:reshape2㤼㸲:

    dcast, melt

The following object is masked from 㤼㸱package:DescTools㤼㸲:

    %like%

Registered S3 method overwritten by 'GGally':
  method from   
  +.gg   ggplot2
sROC 0.1-2 loaded
constSum(constant.sum,100)

In order to anwser this question we need to conduct a repeated measures ANOVA. This type of ANOVA is used for analyzing data where the same subjects are measured more than once. In our case we have every respondent measured on each of the factors (locations, price, ambience and customer service). Repeated measures ANOVA is an extension of the paired-samples t-test. This test is also referred to as a within-subjects ANOVA. In the within-subject experimental design the same individuals are measured on the same outcome variable under different time points or conditions.

We need to check all assumptions that need to be fulfilled in order to deploy this type of ANOVA. There are three assumputions that need to check. The first to check that each level of the independent variable is approximately normally distributed. Since we have more than 30 observations at each level, we do not need to proceed further due to the central limit theorem. Second assumption referrs to extreme outliers. Let’s have a look at potential outliers:

# Outliers
constant.sum.long %>% 
  group_by(Factor) %>%
  identify_outliers(Points)

As we cannot identify any extreme outliers, we can proceed with deploying repeated measures ANOVA.

# Formatting data 
constant.sum.aov <- gather(constant.sum, key = "Factor", value = "Points", ` Location`,` Price`,` Ambience`,` Customer Service`)
attributes are not identical across measure variables;
they will be dropped
# One-way repeated measures ANOVA  
res.aov <- anova_test(data = constant.sum.aov, dv = Points,wid = id ,within = Factor)
get_anova_table(res.aov)
ANOVA Table (type III tests)

  Effect  DFn    DFd      F        p p<.05   ges
1 Factor 2.56 297.36 33.668 1.06e-16     * 0.225
# Post hoc test
pairwise.t.test(constant.sum.long$Points,constant.sum.long$Factor, paired = T, p.adjust.method = "holm")

    Pairwise comparisons using paired t tests 

data:  constant.sum.long$Points and constant.sum.long$Factor 

                   Location  Price   Ambience  Customer Service
 Price            3.7e-15   -       -         -                
 Ambience         3.2e-10   0.030   -         -                
 Customer Service < 2e-16   0.742   0.079     -                
id                < 2e-16   1.2e-11 3.1e-16   3.0e-12          

P value adjustment method: holm 
ggstatsplot::ggwithinstats(
  data = constant.sum.long %>% filter(Factor!="id"), # excluding "id" column from the data
  x = Factor,
  y = Points,
  type = "p",
  pairwise.comparisons = TRUE, # show pairwise comparison test results
  title = "What factors do you consider when choosing a place to go for a dinner?")

Text or number entry question

Error: unexpected symbol in "A text"

A text or number entry question is a recommended type of question if you are interested in obtaining ratio data type. We will use this type of question together with a constant sum question type to collect data that can be analysed with regression analysis. Note that in this case we treat constant sum data as ratio data and therefore assume that 0 means complete absence.

Here is a glimpse in answers on how important is each factor to our respondents when it comes to dinning outside:

Constant sum question
Location Price Ambience Customer Service
32 23 32 1
25 30 22 43
19 21 30 34
20 20 20 46
30 30 10 17
0 20 20 4

We asked our respondents how much are they willing to spend on dinner on average:

x
29
77
52
31
22
35

In order to handle data easier, we will create a new data frame:

Location Price Ambience Customer Service Willingness-to-pay (in EUR)
32 23 32 1 29
25 30 22 43 77
19 21 30 34 52
20 20 20 46 31
30 30 10 17 22
0 20 20 4 35

Before we conduct a linear regression analysis, we need to take a look at correlation matrix:

correlation
                               Location       Price    Ambience  Customer Service  Willingness-to-pay (in EUR)
 Location                     1.0000000 -0.31732620 -0.36134355       -0.16688104                   0.14145397
 Price                       -0.3173262  1.00000000 -0.21962027        0.08894752                  -0.07438388
 Ambience                    -0.3613436 -0.21962027  1.00000000       -0.02405881                  -0.32550607
 Customer Service            -0.1668810  0.08894752 -0.02405881        1.00000000                   0.12125571
 Willingness-to-pay (in EUR)  0.1414540 -0.07438388 -0.32550607        0.12125571                   1.00000000

From our data we see, for instance, that some negative correlation between willingness to pay and importance of ambience as well as some positive correlation between importance of customer service and wilingness-to-pay. Let us observe descriptive statistics as well:

We see that difference between mean and median does not suggest (at the first sight) great effect of outliers. Let us now do linear regression analysis:

summary(mlr.dinner)

Call:
lm(formula = ` Willingness-to-pay (in EUR)` ~ ` Location` + ` Price` + 
    ` Ambience` + ` Customer Service`, data = dinner)

Residuals:
    Min      1Q  Median      3Q     Max 
-40.810 -18.205  -3.314  14.059  74.274 

Coefficients:
                    Estimate Std. Error t value Pr(>|t|)    
(Intercept)         55.31553   11.57393   4.779 5.38e-06 ***
` Location`         -0.06739    0.25556  -0.264 0.792503    
` Price`            -0.28455    0.16117  -1.765 0.080205 .  
` Ambience`         -0.69755    0.19088  -3.654 0.000394 ***
` Customer Service`  0.10988    0.07931   1.386 0.168646    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.72 on 112 degrees of freedom
Multiple R-squared:  0.1449,    Adjusted R-squared:  0.1144 
F-statistic: 4.745 on 4 and 112 DF,  p-value: 0.001421
[1] -0.697554

Out of all factors of importance when dinning out, the only one that suggests significance at 0.05 level of significance is ambience. From the summary we can conclude that increase in importance of ambience by 1 point, leads to decrease in willingness to pay by -0.697554.

confint(mlr.dinner)

From confidence intervals, We can conclude that when we do not consider any of given factors (location, price, ambience and customer service), willingness to pay will be somewhere between 32.383272EUR and 78.2477971EUR. Besides that, for each increase in importance of dinner ambience by one point, there will be an average decrease of willingness to pay between -1.0757599 and -0.3193481.

ggcoefstats(x = mlr.dinner,
            title = "Willingness to pay predicted by importance of factors")
New names:
* NA -> ...1
* NA -> ...2
* NA -> ...3
* NA -> ...4

head(mlr.dinner)
$coefficients
        (Intercept)         ` Location`            ` Price`         ` Ambience` ` Customer Service` 
        55.31553453         -0.06738863         -0.28455041         -0.69755404          0.10987936 

$residuals
          1           2           3           4           5           6           7           8           9 
  4.5974109  42.5270700  21.1311310  -8.3801234 -17.6497720  -1.1129630  24.7279650  15.0957023 -14.7317093 
         10          11          12          13          14          15          16          17          18 
 -6.7919381  28.1692734  70.5603687   4.2604480 -30.1689386 -38.9408794  14.9643486  -3.0084303 -19.9164197 
         19          20          21          22          23          24          25          26          27 
-19.8496472 -13.7319330 -24.5598418   0.4520224 -27.6200390   7.5009262 -25.4469611   0.4951058   7.7781206 
         28          29          30          31          32          33          34          35          36 
 -2.9577776  -4.1994345  -4.2200885   4.9812544 -16.8746299 -29.6235789  11.4411945 -39.1641624  -9.9651152 
         37          38          39          40          41          42          43          44          45 
 20.5212991 -27.9910349 -15.1475455 -20.5436827 -35.1469908   4.6742774 -40.8100647  64.1979622 -10.6019464 
         46          47          48          49          50          51          52          53          54 
 -0.1201006 -23.4935271  -7.0903019  74.2735905  18.5939073 -31.6631303 -22.3566918  29.3706242  34.7009679 
         55          56          57          58          59          60          61          62          63 
-19.7301996 -18.2047574 -24.4713711 -16.7198606 -34.4003299  37.0997394   8.3801848 -20.6009102  30.7161163 
         64          65          66          67          68          69          70          71          72 
  8.4764821  -4.6369372  -4.8196905   5.0871047   7.1303365   2.4064275  -1.2261667  17.8051417 -11.7150348 
         73          74          75          76          77          78          79          80          81 
 -7.1938954  15.2770808  14.0593940   8.3219862  15.2005160   6.5578072  60.7761138 -26.6765041  19.4487559 
         82          83          84          85          86          87          88          89          90 
 15.3373513  15.8118595  -4.5963578  32.8285495  32.7819183 -19.1850977 -20.7732909   2.7919995  61.7519275 
         91          92          93          94          95          96          97          98          99 
-37.0230404  12.4893013 -28.3556793  -1.2398640 -16.1755295   8.7796381  -9.5643367 -18.4302790  39.0850564 
        100         101         102         103         104         105         106         107         108 
-15.5522959 -21.7430188  19.6624288 -16.2158432  54.2544197 -18.9053495  -3.3136166 -20.0636354   2.9142350 
        109         110         111         112         113         114         115         116         117 
 -5.2204194 -10.3579518   2.2229113 -12.4282643 -13.5832652  33.9596531 -17.7133014  10.8527202 -12.5666327 

$effects
        (Intercept)         ` Location`            ` Price`         ` Ambience` ` Customer Service` 
       -356.8571262         -40.0194740          -8.7999110         -93.5225302          34.2504874 
                                                                                                    
          6.0178811          28.3122168          18.0496272          -9.5032363         -10.1917480 
                                                                                                    
         25.5291331          74.8517222           8.9093534         -23.0125697         -43.1163183 
                                                                                                    
         15.3402668         -10.3432140         -23.0862119         -26.2426432         -15.7133239 
                                                                                                    
        -32.9459721          -2.1444338         -28.8135829           5.7803827         -20.5882130 
                                                                                                    
          3.8185103           7.7130893          -5.2625568          -3.9807909         -10.7730116 
                                                                                                    
          8.3880565          -7.6250882         -28.4833227           9.7716557         -40.0021703 
                                                                                                    
         -7.9363372          19.2013550         -28.5171908         -15.5594741         -16.4606086 
                                                                                                    
        -36.3862347          10.4754498         -40.4448010          60.2979507          -8.6847432 
                                                                                                    
         -1.0328674         -23.0597361           2.6325373          68.4096098          18.8098984 
                                                                                                    
        -35.0103722         -12.5855004          32.9240464          44.5380792         -18.6928796 
                                                                                                    
        -12.9305846         -26.3587098          -6.8370944         -29.7216839          46.3991517 
                                                                                                    
         14.3965046         -11.9671154          29.6460749           6.8856726          -3.9598215 
                                                                                                    
         -2.3122652          -1.5518685           5.8305450           6.7066649          -3.0691848 
                                                                                                    
         22.4065767         -15.5670854          -9.7224609          12.8197400          11.3533788 
                                                                                                    
          7.5673759          10.0597804           7.1883412          56.2229478         -31.6222673 
                                                                                                    
         20.6555235          19.5340161          21.5121116         -11.1668035          30.5836589 
                                                                                                    
         30.7171299         -24.4979333         -21.8896688           9.2386143          57.6625386 
                                                                                                    
        -40.2957687          13.3243282         -31.4549283           1.0723707         -14.1239240 
                                                                                                    
          0.7572913         -12.2528292         -17.7505108          52.1500398         -22.1975006 
                                                                                                    
        -23.1315352          20.8093078         -10.3487959          49.2050839         -23.8033969 
                                                                                                    
         -6.0742157         -17.2241830          -3.7025472          -3.7361635         -14.5132157 
                                                                                                    
          3.1062906         -11.0265242         -16.2584508          38.8602697         -18.5466410 
                                        
          7.0086718         -13.6803582 

$rank
[1] 5

$fitted.values
        1         2         3         4         5         6         7         8         9        10 
24.402589 34.472930 30.868869 39.380123 39.649772 36.112963 23.272035 43.904298 27.731709 22.791938 
       11        12        13        14        15        16        17        18        19        20 
38.830727 13.439631  2.739552 33.168939 39.940879 29.035651 38.008430 46.916420 36.849647 37.731933 
       21        22        23        24        25        26        27        28        29        30 
32.559842 45.547978 43.620039 44.499074 25.446961 16.504894 31.221879 34.957778 32.199434 47.220088 
       31        32        33        34        35        36        37        38        39        40 
25.018746 23.874630 29.623579 28.558806 41.164162 22.965115 39.478701 31.991035 23.147545 32.543683 
       41        42        43        44        45        46        47        48        49        50 
45.146991 25.325723 47.810065 22.802038 24.601946 22.120101 40.493527 36.090302 27.726410 39.406093 
       51        52        53        54        55        56        57        58        59        60 
48.663130 27.356692 40.629376 37.299032 20.730200 26.204757 27.471371 25.719861 34.400330 46.900261 
       61        62        63        64        65        66        67        68        69        70 
33.619815 20.600910 25.283884 52.523518 38.636937 30.819690 45.912895 35.869664 32.593573 35.226167 
       71        72        73        74        75        76        77        78        79        80 
42.194858 42.715035 37.193895 32.722919 38.940606 49.678014 35.799484  9.442193 49.223886 42.676504 
       81        82        83        84        85        86        87        88        89        90 
30.551244 22.662649  8.188140 38.596358 38.171450 29.218082 33.185098 25.773291 50.208001 41.248072 
       91        92        93        94        95        96        97        98        99       100 
38.023040 36.510699 31.355679 33.239864 17.175530 48.220362 47.564337 31.430279 31.914944 19.552296 
      101       102       103       104       105       106       107       108       109       110 
36.743019 27.337571 25.215843 32.745580 32.905349 21.313617 23.063635 39.085765 15.220419 41.357952 
      111       112       113       114       115       116       117 
27.777089 37.428264 21.583265 60.040347 25.713301 31.147280 18.566633 

$assign
[1] 0 1 2 3 4

LS0tDQp0aXRsZTogIjE4LVF1ZXN0aW9ubmFpcmVfZGVzaWduIg0Kb3V0cHV0Og0KICBwZGZfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQotLS0NCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KDQojIFF1ZXN0aW9ubmFpcmUgZGVzaWduICANCldlbGNvbWUgdG8gdGhlIHF1ZXN0aW9ubmFpcmUgZGVzaWduIGd1aWRlIQ0KDQpBbiBhaW0gb2YgdGhpcyBjb3Vyc2UgaXMgdG8gZGV2ZWxvcCB5b3VyIGFiaWxpdHkgdG8gdHJhbnNsYXRlIGJ1c2luZXNzIHByb2JsZW1zIGludG8gYWN0aW9uYWJsZSByZXNlYXJjaCBxdWVzdGlvbnMgYW5kIHRvIGRlc2lnbiBhbiBhZGVxdWF0ZSByZXNlYXJjaCBwbGFuIHRvIGFuc3dlciB0aGVzZSBxdWVzdGlvbnMuIFRoZXJlZm9yZSwgeW91IG5lZWQgdG8gYmUgZXF1aXBlZCB3aXRoIGtub3dsZWRnZSBvbiBob3cgdG8gY3JlYXRlIGEgc3VydmV5IGFuZCBwcm9wZXJseSBjb25kdWN0IGEgcmVzZWFyY2guIA0KDQpHZW5lcmFsbHksIHdoYXQgeW91IGNhbiBleHBlY3QgZnJvbSB0aGUgc3VydmV5IGRlc2lnbiBpcyBzaW1pbGFyIHRvIHdoYXQgb25lIGV4cGVyaWVuY2VzIGluIGEgcmVsYXRpb25zaGlwLiBJZiB5b3UgdHJ5IHRvIHRha2UgbW9yZSB0aGFuIHlvdSBjb21taXQsIGl0IGRvZXNu4oCZdCB3b3JrIG91dC4gTm93IG9uIGEgc2VyaW91cyBub3RlLCBpZiB5b3UgZm9sbG93IGd1aWRlbGluZXMgbWVudGlvbmVkIGhlcmUsIHlvdSB3aWxsIGNlcnRhaW5seSBhdm9pZCB1c3VhbCB0cmFwcyB5b3VyIGZlbGxvdyBjb2xsZWd1ZXMgd2VyZSBjYXVnaHQgaW4uDQoNCkluIGEgcmVzZWFyY2ggcHJvY2VzcywgY29uZHVjdGluZyBhIHN1cnZleSBpcyBhIHBhcnQgb2YgKHByaW1hcnkpIGRhdGEgY29sbGVjdGlvbi4gQmVmb3JlIHdlIGNvbGxlY3QgZGF0YSwgd2UgaGF2ZSB0byBtYWtlIHN1cmUgdGhhdCBwcmVjZWRpbmcgc3RlcHMgYXJlIGNvcnJlY3RseSBkb25lLiBIb3dldmVyLCBpbiB0aGUgZm9sbG93aW5nIHNlY3Rpb25zIHdlIHdpbGwgZm9jdXMgb24gdGhlIHByb2Nlc3Mgb2YgZGVzaWduaW5nIGEgcXVlc3Rpb25uYWlyZS4gRXZlbnR1YWxseSwgeW91IHdpbGwgYmUgYWJsZSB0byBjb2xsZWN0IHJlbGV2YW50IGRhdGEgYW5kIGFwcGx5IGFwcHJvcHJpYXRlIHN0YXRpc3RpY2FsIHRlc3RzLiAgICANCg0KYGBge3IsZWNobz1GQUxTRSxvdXQud2lkdGggPSAnNzAlJyxmaWcuYWxpZ249J2NlbnRlcid9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygicmVzZWFyY2gtcHJvY2Vzcy5QTkciKQ0KYGBgDQoNCg0KIyMgUXVlc3Rpb25uYWlyZSBkZXNpZ24gcHJvY2VzcyAgDQpBIHN0cnVjdHVyZWQgcXVlc3Rpb25uYWlyZSBpcyBhIHJlc2VhcmNoIGluc3RydW1lbnQgZGVzaWduZWQgdG8gZWxpY2l0IHNwZWNpZmljIGluZm9ybWF0aW9uIGZyb20gYSBzYW1wbGUgb2YgYSB0YXJnZXQgcG9wdWxhdGlvbi4gVXN1YWxseSBpdCBpcyB1c2VkIGluIGEgc3RhbmRhcmRpemVkIHdheSB3aXRoIGZpeGVkLWFsdGVybmF0aXZlIHF1ZXN0aW9ucyAoc2FtZSBxdWVzdGlvbnMgYW5kIHJlc3BvbnNlIG9wdGlvbnMgZm9yIGFsbCByZXNwb25kZW50cykuDQoNCkFuIG9iamVjdGl2ZSBvZiBhIHF1ZXN0aW9ubmFpcmUgaXMgdGhyZWVmb2xkOg0KDQoqIHRvIHRyYW5zbGF0ZSB0aGUgaW5mb3JtYXRpb24gbmVlZCBpbnRvIGEgc2V0IG9mIHNwZWNpZmljIHF1ZXN0aW9ucyB0aGF0IHRoZSByZXNwb25kZW50IGNhbiBhbmQgd2lsbCBhbnN3ZXIsDQoqIHRvIG1vdGl2YXRlLCBhbmQgZW5jb3VyYWdlIHJlc3BvbmRlbnRzIHRvIGJlY29tZSBpbnZvbHZlZCwgdG8gY29vcGVyYXRlLCBhbmQgdG8gY29tcGxldGUgdGhlIHF1ZXN0aW9ubmFpcmUsDQoqICB0byBtaW5pbWl6ZSByZXNwb25zZSBlcnJvci4NCg0KSW4gb3JkZXIgdG8gbWVldCB0aGVzZSBvYmplY3RpdmVzLCBhIHF1ZXN0aW9ubmFpcmUgZGVzaWduIHByb2Nlc3Mgc3VnZ2VzdHMgdGhlIGZvbGxvd2luZyBzZXF1ZW5jZSBvZiBzdGVwczoNCg0KYGBge3IsZWNobz1GQUxTRSwgb3V0LndpZHRoID0gJzcwJScsZmlnLmFsaWduPSdjZW50ZXInfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoInF1ZXN0aW9ubmFpcmUtZGVzaWduLXByb2Nlc3MucG5nIikNCmBgYA0KDQojIyMgU3BlY2lmaWNhdGlvbiBvZiB0aGUgaW5mb3JtYXRpb24gbmVlZGVkICANClRoZSBxdWVzdGlvbm5haXJlIGRlc2lnbiBzaG91bGQgYmUgYWxpZ25lZCB3aXRoIHRoZSByZXNlYXJjaCBkZXNpZ24hDQpJbiBvcmRlciB0byBkbyBtYWtlIGl0IGFsaWduZWQsIGl0IGlzIG5lY2Vzc2FyeSB0byByZXZpZXcgY29tcG9uZW50cyBvZiB0aGUgcHJvYmxlbSBhbmQgdGhlIGFwcHJvYWNoLiBJbiBwYXJ0aWN1bGFyLCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgcmVzZWFyY2ggcXVlc3Rpb25zLCBoeXBvdGhlc2VzIGFuZCBjaGFyYWN0ZXJpc3RpY3MgdGhhdCBpbmZsdWVuY2UgdGhlIHJlc2VhcmNoIGRlc2lnbi4gIA0KDQpJZiB5b3UgYXJlIGludGVyZXN0ZWQgaW4gdGhlIGNhdXNhbCBlZmZlY3Qgb2Ygb25lIHBhcnRpY3VsYXIgKGluZGVwZW5kZW50KSB2YXJpYWJsZSBvbiBhbm90aGVyIChkZXBlbmRlbnQpIHZhcmlhYmxlLCB0aGluayBhYm91dCBhbiBleHBlcmltZW50YWwgZGVzaWduIHRoYXQgbWlnaHQgYWxsb3cgeW91IHRvIG1hbmlwdWxhdGUgdGhpcyB2YXJpYWJsZS4gSW4gdGhpcyBjYXNlLCB5b3UgcGFydGljdWxhcmx5IGhhdmUgdG8gZGVjaWRlIG9uIHRoZSBmb2xsb3dpbmc6ICANCg0KKiBXaGljaCB2YXJpYWJsZSB0byBtYW5pcHVsYXRlPyAgDQoqIFdoZXRoZXIgdG8gdXNlIGEgYmV0d2Vlbi1zdWJqZWN0cyBvciB3aXRoaW4tc3ViamVjdHMgZGVzaWduPyAgDQoqIFRoZSBjYXVzZS1lZmZlY3Qgc2VxdWVuY2UgKHRoZSBjYXVzZSBtdXN0IG9jY3VyIGJlZm9yZSB0aGUgZWZmZWN0KSAgDQoqIFRoZSBudW1iZXIgb2YgZXhwZXJpbWVudGFsIGNvbmRpdGlvbnMgIA0KKiBQb3RlbnRpYWwgaW50ZXJhY3Rpb25zIGFuZCByZWxhdGlvbnNoaXBzIHdpdGggb3RoZXIgdmFyaWFibGVzIChkb2VzIHRoZSBlZmZlY3QgZGVwZW5kIG9uIGFub3RoZXIgdmFyaWFibGU/KQ0KDQpXaGF0IHlvdSBuZWVkIHRvIGJlIGNhcmVmdWwgYWJvdXQgaXMgdGhlIGVmZmVjdCBvZiAqKnJldmVyc2VkIGNhdXNhdGlvbioqLiBUaGUgZWZmZWN0IHJlZmVycyB0byB0aGUgc2l0dWF0aW9uIHdoZXJlIHRoZSBjYXVzYWwgcmVsYXRpb25zaGlwIGNvdWxkIHBvc3NpYmxlIGhhdmUgYW4gb3Bwb3NpdGUgZGlyZWN0aW9uIGZyb20gd2hhdCB3ZSBhc3N1bWVkIGF0IHRoZSBmaXJzdCBwbGFjZS4gRm9yIGluc3RhbmNlLCBpdCBpcyBvZnRlbiBhc3N1bWVkIHRoYXQgYW4gaW5jcmVhc2UgaW4gaW5kaXZpZHVhbCBpbmNvbWUgbGVhZHMgdG8gaW5jcmVhc2UgaW4gd2VsbC1iZWluZyAoaGFwcGluZXNzKS4gSG93ZXZlciwgc29tZSBbcmVzZWFyY2hlc10oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMTY5NDk2OTIpIHN1Z2dlc3QgdGhhdCB0aGlzIGNhdXNhdGlvbiBjb3VsZCBoYXZlIGFuIG9wcG9zaXRlIGRpcmVjdGlvbiwgaS5lLiB0aGF0IGFjdHVhbGx5IGluY3JlYXNlIGluIHdlbGwtYmVpbmcgb2YgYW4gaW5kaXZpZHVhbCBsZWFkcyB0byBhbiBpbmNyZWFzZSBpbiBpbmNvbWUuICANCg0KSGVyZSBhcmUgc29tZSBleGFtcGxlcyBvZiBjYXVzYWwgcmVzZWFyY2ggZGVzaWduIGFwcGxpY2F0aW9uczogIA0KDQoqIFRvIGFzc2VzcyBob3cgYSBwcm9kdWN0J3MgY291bnRyeS1vZi1vcmlnaW4gaW1wYWN0cyBhdHRyYWN0aXZlbmVzcyBhY3Jvc3MgZGlmZmVyZW50IGNvdW50cmllcy4gIA0KKiBUbyBhbmFseXNlIHRoZSBlZmZlY3RzIG9mIHJlYnJhbmRpbmcgb24gY3VzdG9tZXIgbG95YWx0eS4gIA0KDQpgYGB7cixlY2hvPUZBTFNFLCBvdXQud2lkdGggPSAnNzAlJyxmaWcuYWxpZ249J2NlbnRlcid9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiY2F1c2F0aW9uLWVmZmVjdC5wbmciKQ0KYGBgDQoNCg0KSWYgeW91IHdvdWxkIGxpa2UgdG8gYW5hbHl6ZSB0aGUgZWZmZWN0cyBvZiBtdWx0aXBsZSBjYXRlZ29yaWNhbCBvciBjb250aW51b3VzIChpbmRlcGVuZGVudCkgdmFyaWFibGVzIG9uIG9uZSBjb250aW51b3VzIChkZXBlbmRlbnQpIHZhcmlhYmxlLCB5b3UgbWlnaHQgdXNlIGEgcmVncmVzc2lvbiBtb2RlbC4gV2hlbiBkb2luZyB0aGlzLCB5b3UgcGFydGljdWxhcmx5IGhhdmUgdG8gZGVjaWRlIG9uOiAgDQoNCiogSG93IHRvIG1lYXN1cmUgKip0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChEVikqKi4gVGhpcyBpcyBwYXJ0aWN1bGFybHkgaW1wb3J0YW50LCBzaW5jZSB5b3UgbmVlZCBhIHZhcmlhYmxlIHRoYXQgaXMgcG93ZXJmdWwgaW4gdW5jb3ZlcmluZyB2YXJpYXRpb24gYmV0d2VlbiBzdWJqZWN0cyAoZS5nLiwgb3Blbi1lbmRlZCBxdWVzdGlvbnMsIHN1Y2ggYXMgIkhvdyBtdWNoIGFyZSB5b3Ugd2lsbGluZyB0byBwYXkgZm9yIHRoaXMgcHJvZHVjdCIgYXJlIGdvb2QgY2FuZGlkYXRlcykuIE1vcmVvdmVyLCB5b3UgYWxzbyBuZWVkIHRvIGNvbnNpZGVyIHRoZSBuYXR1cmUgb2YgeW91ciBEVixpLmUuIHdoZXRoZXIgaXQgaXMgYW4gaW50ZXJ2YWwgdmFyaWFibGUsIG9yZGluYWwgb3IgY2F0ZWdvcmljYWwgdmFyaWFibGUuIFRoZSBuYXR1cmUgb2YgeW91ciBEViB3aWxsIGhlYXZpbHkgaW5mbHVlbmNlIHlvdXIgY2hvaWNlIG9mIGEgY29ycmVjdCBzdGF0aXN0aWNhbCB0ZXN0Lg0KDQoqIEhvdyB0byBtZWFzdXJlICoqdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcyAoSVYpKiogKHNpbmdsZS1pdGVtIHZzLiBtdWx0aS1pdGVtIHNjYWxlcywgY2F0ZWdvcmljYWwgdnMuIGNvbnRpbnVvdXMpLiBCZWFyIGluIG1pbmQgdGhhdCB0aGUgbmF0dXJlIG9mIHRoZSBJViwgdG9nZXRoZXIgd2l0aCBEViwgYWZmZWN0cyB5b3VyIGNob2ljZSBvZiBhIHN0YXRpc3RpY2FsIHRlc3QgYXMgd2VsbC4gIA0KDQoqIFdoYXQgb3RoZXIgdmFyaWFibGVzIG1pZ2h0IGNhdXNlIHRoZSBlZmZlY3QgdGhhdCB5b3Ugd291bGQgbGlrZSB0byBpbnZlc3RpZ2F0ZSAodG8gcHJldmVudCBvbWl0dGVkIHZhcmlhYmxlIGJpYXMsIGkuZS4gdmFyaWFibGVzIHRoYXQgYXJlIG5vdCBwYXJ0IG9mIHlvdXIgbW9kZWwgYnV0IHN0aWxsIGluZmx1ZW5jZSB0aGUgZGVwZW5kZW50IHZhcmlhYmxlKS4NCg0KKiBQb3RlbnRpYWwgaW50ZXJhY3Rpb25zIChlLmcuLCBpcyB0aGUgZWZmZWN0IG9mIHZhcmlhYmxlIFggc3Ryb25nZXIgZm9yIGdyb3VwIEEgdnMuIEI/KQ0KDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGggPSAnNzAlJyxmaWcuYWxpZ249J2NlbnRlcid9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygibWxwLXJlZ3Jlc3Npb24ucG5nIikNCmBgYA0KDQojIyMgU3BlY2lmeSB0aGUgaW50ZXJ2aWV3aW5nIG1ldGhvZCAgDQpJbiB0aGUgbmV4dCBzdGVwIHlvdSBzaG91bGQgcmV2aWV3IHRoZSB0eXBlIG9mIGludGVydmlld2luZyBtZXRob2QgeW91IHdpbGwgdXNlLg0KQXQgdGhpcyBwb2ludCB5b3UgbmVlZCB0byB0aGluayBpbiB3aGljaCBzZXR0aW5nIHlvdSBhaW0gdG8gY29uZHVjdCB5b3VyIHN1cnZlcnkuIEZvciBpbnN0YW5jZSwgc2hvdWxkIHlvdSBkbyBpdCBpbiBhIGZhY2UtdG8tZmFjZSBzZXR0aW5nIG9yIHJhdGhlciBvbmxpbmUuIEhlcmUgeW91IGNhbiBmaW5kIHNvbWUgYWR2YW50YWdlcyBhbmQgZGlzYWR2YW50YWdlcyBvZiBvbmxpbmUgc3VydmV5czoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzUwJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiYWR2LWRpc2Fkdi1vbmxpbmUtcXVlc3Rpb25uYWlyZS5wbmciKQ0KYGBgDQoNCkFkZGl0aW9uYWxseSwgaGVyZSBpcyB0aGUgbGlzdCBvZiB0aGUgb25saW5lIHRvb2xzIHlvdSBjYW4gdXNlIHRvIGNvbmR1Y3QgYW4gb25saW5lIHN1cnZleSAodXN1YWxseSBmb3IgZnJlZSk6ICANCg0KLSBbUXVhbHRyaWNzXShodHRwOi8vd3d3LnF1YWx0cmljcy5jb20vZnJlZS1hY2NvdW50LykNCi0gW0dvb2dsZSBmb3JtXShodHRwczovL3d3dy5nb29nbGUuY29tL2Zvcm1zL2Fib3V0LykNCi0gW1N1cnZleSBtb25rZXldKGh0dHBzOi8vd3d3LnN1cnZleW1vbmtleS5jb20vKQ0KLSBbRnJlZSBvbmxpbmUgc3VydmVyeXNdKGh0dHA6Ly9mcmVlb25saW5lc3VydmV5cy5jb20vKQ0KLSBbS3dpayBzdXJ2ZXlzXShodHRwOi8va3dpa3N1cnZleXMuY29tLykNCg0KIyMjIERldGVybWluZSB0aGUgY29udGVudCBvZiBxdWVzdGlvbnMgIA0KSW4gdGhpcyBzdGVwIHlvdSBhcmUgc3RhcnRpbmcgdG8gd29yayBvbiB0aGUgY29udGVudCBvZiB5b3UgcXVlc3Rpb25zLiBUaGVyZSBhcmUgc2V2ZXJhbCBxdWVzdGlvbnMgeW91IHNob3VsZCBhc2sgeW91cnNlbGYgd2hlbiB3cml0aW5nIHF1ZXN0aW9uczogIA0KDQoqIElzIHRoZSBxdWVzdGlvbiBuZWNlc3Nhcnk/DQoqIFdpbGwgSSBvYnRhaW4gdGhlIG5lZWRlZCBpbmZvcm1hdGlvbj8gIA0KKiBBcmUgc2V2ZXJhbCBxdWVzdGlvbnMgbmVlZGVkIGluc3RlYWQgb2Ygb25lPyAgDQoqIFdoYXQgdHlwZSBvZiBkYXRhIGNhbiBJIGNvbGxlY3QgYnkgYXNraW5nIHRoYXQgcXVlc3Rpb24gKGNhdGVnb3JpY2FsIG9yIGNvbnRpbnVpb3VzKT8gIA0KDQpJbiB5b3VyIHN1cnZleSB0cnkgdG8gYXZvaWQgYXNraW5nICoqZG91YmxlLWJhcnJlbGxlZCBxdWVzdGlvbnMuKipUaG9zZSBhcmUgDQphIHNpbmdsZSBxdWVzdGlvbiB0aGF0IGF0dGVtcHRzIHRvIGNvdmVyIHR3byBpc3N1ZXMuIFN1Y2ggcXVlc3Rpb25zIGNhbiBiZSBjb25mdXNpbmcgdG8gcmVzcG9uZGVudHMgYW5kIHJlc3VsdCBpbiBhbWJpZ3VvdXMgcmVzcG9uc2VzLiBJbnN0ZWFkLCB5b3UgbWlnaHQgYXNrIG11bHRpcGxlIHF1ZXN0aW9ucyBpbiBvcmRlciB0byBvYnRhaW4gdGhlIGludGVkZWQgaW5mb3JtYXRpb24uICANCg0KPHNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij48Qj5JbmNvcnJlY3Q6PC9CPjwvc3Bhbj4gIA0KRG8geW91IHRoaW5rIE5pa2UgVG93biBvZmZlcnMgYmV0dGVyIHZhcmlldHkgYW5kIHByaWNlcyB0aGFuIG90aGVyIE5pa2Ugc3RvcmVzPyAgICANCg0KPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPjxCPkNvcnJlY3Q6PC9CPjwvc3Bhbj4gIA0KRG8geW91IHRoaW5rIE5pa2UgVG93biBvZmZlcnMgYmV0dGVyIHZhcmlldHkgdGhhbiBvdGhlciBOaWtlIHN0b3Jlcz8gIA0KRG8geW91IHRoaW5rIE5pa2UgVG93biBvZmZlcnMgYmV0dGVyIHByaWNlcyB0aGFuIG90aGVyIE5pa2Ugc3RvcmVzPw0KICAgICAgICAgICANCiMjIyBJbmFiaWxpdHkgYW5kIHVud2lsbGluZ25lc3MgdG8gYW5zd2VyICANClRoZSBxdWFsaXR5IG9mIGNvbGxlY3RlZCBkYXRhIHlvdSBoaWdobHkgZGVwZW5kcyBvbiB5b3VyIGFiaWxpdHkgdG8gYWRkcmVzcyBjb3JyZWN0IHBhcnRpY2lwYW50cy4gVGhlcmVmb3JlLCB5b3UgbmVlZCB0byBtYWtlIHN1cmUgdGhhdCB5b3VyIHJlc3BvbmRlbnRzIGFyZSBhYmxlIHRvIG1lYW5pbmdmdWxseSBhbnN3ZXIgeW91ciBxdWVzdGlvbnMuICAgDQoNCkV4YW1wbGVzOiAgDQoNCiogTm90IGV2ZXJ5IGhvdXNlaG9sZCBtZW1iZXIgbWlnaHQgYmUgaW5mb3JtZWQgYWJvdXQgbW9udGhseSBleHBlbnNlcyBmb3IgZ3JvY2VyaWVzIHB1cmNoYXNlcyBpZiBzb21lb25lIGVsc2UgbWFrZXMgdGhlc2UgcHVyY2hhc2VzLiAgIA0KKiBVc2UgZmlsdGVyIHF1ZXN0aW9ucyB0aGF0IG1lYXN1cmUgZmFtaWxpYXJpdHkgYW5kIHByb2R1Y3QgdXNlLiAgDQoqIEluY2x1ZGUgYSDigJxkb27igJl0IGtub3figJ0gb3B0aW9uLiAgDQoqIElmIHlvdSBhc2sgcGFydGljaXBhbnRzIGZvciBtb250ZXJheSB2YWx1ZXMgKGUuZy4gaG93IG11Y2ggYXJlIHlvdSByZWFkeSB0byBwYXkgZm9yIHRoZSBYWSBwcm9kdWN0PykgYWNyb3NzIHNldmVyYWwgRVUsIG1ha2Ugc3VyZSB5b3UgaW5kaWNhdGUgY29ycmVjdCBjdXJyZW5jeSAoZS5nLiBIUksgZm9yIENyb2F0aWEgb3IgSFVGIGZvciBIdW5nYXJ5KS4gIA0KKiBUaGluayBhYm91dCBob3cgbW9iaWxlIGZyaWVuZGx5IGlzIHRoZSBsYXlvdXQgb2YgeW91ciBzdXJ2ZXkgKGlmIGl0IGlzIGFuIG9ubGluZSBzdXJ2ZXkpLg0KKiBHb29kIGNhc2UgcHJhY3RpY2VzIHN1Z2dlc3QgdGhhdCB0aGVyZSBzaG91bGQgbm90IGJlIG1vcmUgdGhhbiAyIHF1ZXN0aW9ucyBwZXIgcGFnZSAoZm9yIG9ubGluZSBzdXJ2ZXlzIGRpc3BsYXllZCBvbiBtb2JpbGUgcGhvbmVzKS4NCg0KDQoNCklmIHlvdSBhcmUgYXNraW5nIHBhcnRpY2lwYW50cyB0byByZWNhbGwgY2VydGFpbiBicmFuZHMgZm9yIGluc3RhbmNlLCBtYWtlIHN1cmUgeW91IHVzZSAqKnVuYWlkZWQgcmVjYWxsIHF1ZXN0aW9uOioqICANCg0KPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPjxCPkV4YW1wbGUgb2YgdW5haWRlZCByZWNhbGwgcXVlc3Rpb246PC9CPjwvc3Bhbj4gIA0KV2hhdCBicmFuZHMgb2Ygc29mdCBkcmlua3MgZG8geW91IHJlbWVtYmVyIGJlaW5nIGFkdmVydGlzZWQgb24gVFYgbGFzdCBuaWdodD8gIA0KPHNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij48Qj5FeGFtcGxlIG9mIGFpZGVkIHJlY2FsbCBxdWVzdGlvbjo8L0I+PC9zcGFuPiAgDQpXaGljaCBvZiB0aGVzZSBicmFuZHMgd2VyZSBhZHZlcnRpc2VkIGxhc3QgbmlnaHQgb24gVFY/ICANCmEpIENvY2EtQ29sYSAgDQpiKSBQZXBzaSAgDQpjKSBSZWQgQnVsbCAgICAgICAgDQpkKSBFdmlhbiAgICAgDQplKSBEb27igJl0IGtub3cNCg0KDQoNCklmIHlvdSBhcmUgYXNraW5nIHBhcnRpY2lwYW50cyB0byBsaXN0IHNvbWV0aGluZywgdGhlIGdvb2QgY2FzZSBwcmFjdGljZSBpcyAqKnRvIG1pbmltaXplIHRoZSBlZmZvcnQgcmVxdWlyZWQgYnkgcmVzcG9uZGVudHM6KiogIA0KDQo8c3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiPjxCPkluY29ycmVjdDo8L0I+PC9zcGFuPiAgICAgDQpQbGVhc2UgbGlzdCBhbGwgdGhlIGRlcGFydG1lbnRzIGZyb20gd2hpY2ggeW91IHB1cmNoYXNlZCBtZXJjaGFuZGlzZSBvbiB5b3VyIG1vc3QgcmVjZW50IHNob3BwaW5nIHRyaXAgdG8gZGVwYXJ0bWVudCBzdG9yZSBYLiAgICANCjxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij48Qj5Db3JyZWN0OjwvQj48L3NwYW4+ICAgICANClBsZWFzZSBjaGVjayBhbGwgdGhlIGRlcGFydG1lbnRzIGZyb20gd2hpY2ggeW91IHB1cmNoYXNlZCBtZXJjaGFuZGlzZSBvbiB5b3VyIG1vc3QgcmVjZW50IHNob3BwaW5nIHRyaXAgdG8gYSBkZXBhcnRtZW50IHN0b3JlOiAgICANCmEpIFdvbWVu4oCZcyBkcmVzc2VzICANCmIpIE1lbuKAmXMgYXBwYXJlbCAgDQpjKSBDaGlsZHJlbuKAmXMgYXBwYXJlbCAgDQpkKSBDb3NtZXRpY3MgIA0KZSkgSmV3ZWxyeSAgICANCmYpIE90aGVyIChwbGVhc2Ugc3BlY2lmeSkgX19fX19fX19fX18NCg0KDQpJbiBhIGNhc2UgeW91IGFyZSBhc2tpbmcgZm9yIGluZm9ybWF0aW9uIHRoYXQgY291bGQgYmUgY29uc2lkZXJlZCBzZW5zaXRpdmUgKGUuZy4gbW9uZXksIGZhbWlseSBsaWZlLCBwb2xpdGljYWwgYmVsaWVmcywgcmVsaWdpb24pLCB0aGV5IHNob3VsZCBjb21lIGF0IHRoZSBlbmQgb2YgdGhlIHF1ZXN0aW9ubmFpcmUuIE1vcmVvdmVyLCBpdCBpcyByZWNvbW1lbmRhYmxlIHRvIHByb3ZpZGUgcmVzcG9uc2UgY2F0ZWdvcmllcyByYXRoZXIgdGhhbiBhc2tpbmcgZm9yIHNwZWNpZmljIGZpZ3VyZXM6ICANCg0KPHNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij48Qj5JbmNvcnJlY3Q6PC9CPjwvc3Bhbj4gICAgICAgICANCldoYXQgaXMgeW91ciBob3VzZWhvbGTigJlzIGV4YWN0IGFubnVhbCBpbmNvbWU/ICAgICAgDQo8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+PEI+Q29ycmVjdDo8L0I+PC9zcGFuPiAgICAgICAgICAgDQpXaGljaCBvbmUgb2YgdGhlIGZvbGxvd2luZyBjYXRlZ29yaWVzIGJlc3QgZGVzY3JpYmVzIHlvdXIgaG91c2Vob2xk4oCZcyBhbm51YWwgZ3Jvc3MgaW5jb21lPyAgICANCmEpIHVuZGVyIDI1LjAwMSDigqwgICAgDQpiKSAyNS4wMDHigqwgdG8gNTAuMDAwIOKCrCAgICANCmMpIDUwLjAwMeKCrCB0byA3NS4wMDAg4oKsICAgIA0KZCkgNzUuMDAx4oKsIHRvIDEwMC4wMDAg4oKsICAgDQplKSBvdmVyIDEwMC4wMDAg4oKsICAgDQoNCiMjIyBEZWNpZGUgb24gbWVhc3VyZW1lbnQgc2NhbGVzIGFuZCBzY2FsaW5nIHRlY2huaXF1ZXMNCkV2ZXJ5IHN0YXRpc3RpY2FsIGFuYWx5c2lzIHJlcXVpcmVzIHRoYXQgdmFyaWFibGVzIGhhdmUgYSBzcGVjaWZpYyBsZXZlbHMgb2YgbWVhc3VyZW1lbnQuIE1lYXN1cmVtZW50IHNjYWxlcyB5b3UgY2hvb3NlIGZvciB5b3VyIHF1ZXN0aW9ucyBpbiBhIHN1cnZleSB3aWxsIGFmZmVjdCB0aGUgYW5zd2VycyB5b3UgZ2V0IGFuZCBldmVudHVhbGx5IHN0YXRpc3RpY2FsIHRlc3QgeW91IGNhbiBhcHBseS4NCkZvciBpbnN0YW5jZSwgaXQgd291bGQgbm90IG1ha2Ugc2Vuc2UgdG8gY29tcHV0ZSBhbiBhdmVyYWdlIG9mIGdlbmRlcnMuIEFuIGF2ZXJhZ2Ugb2YgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZSBkb2VzIG5vdCBtYWtlIG11Y2ggc2Vuc2UuIE1vcmVvdmVyLCBpZiB5b3UgdHJpZWQgdG8gY29tcHV0ZSB0aGUgYXZlcmFnZSBvZiBnZW5kZXJzIGRlZmluZWQgaW4gbnVtZXJpYyB2YWx1ZXMgKGUuZy4gbWFsZT0wLCBmZW1hbGU9MSksIHRoZSBvdXRwdXQgd291bGQgYmUgaW50ZXJwcmV0YWJsZS4NCg0KVGhlcmVmb3JlLCBpdCBpcyBjcnVjaWFsIHRvIGJlY29tZSBmYW1pbGlhciB3aXRoIHBvc3NpYmlsaXRpZXMgb2YgZWFjaCBzY2FsZSAqKmJlZm9yZSoqIHlvdSBjaG9vc2UgdG8gYWRkIGFub3RoZXIgcXVlc3Rpb24gdG8geW91ciBzdXJ2ZXkuIENvbnNlcXVlbnRseSwgY2hhbmNlcyB0byBvYnRhaW4gZGF0YSB5b3UgZGlkIG5vdCBpbnRlbmQgdG8gY29sbGVjdCBhbmQgY2hhbmNlcyB0aGF0IHlvdSB3aWxsIG5vdCBiZSBhYmxlIHRvIGFwcGx5IHRlc3RzIHlvdSBpbnRlbmRlZCBhcmUgc2lnbmlmaWNhbnRseSBsb3dlci4NCg0KSW4gdGhlIGZvbGxvd2luZyB0YWJsZSB5b3UgY2FuIGdldCBhIHF1aWNrIG92ZXJ2aWV3IG9mIHBvc3NpYmlsaXRpZXMgcGVyIGVhY2ggbWVhc3VyZW1lbnQgc2NhbGUuIDoNCg0KYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aCA9ICc5MCUnLGZpZy5hbGlnbj0nY2VudGVyJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJtZWFzdXJlbWVudC1zY2FsZS5wbmciKQ0KYGBgDQoNCkluIHRoZSB0YWJsZSBiZWxvdyB5b3UgY2FuIGZpbmQgZ2VuZXJhbCBwcm9jZWR1cmUgZm9yIGNob29zaW5nIGEgY29ycmVjdCBhbmFseXNpcyBiYXNlZCBvbiB0aGUgbWVhc3VyZW1lbnQgc2NhbGUgb2YgeW91ciBkYXRhIGFuZCBudW1iZXIgb2YgdmFyaWFibGVzLiBJdCBzaG93cyBzdGF0aXN0aWNhbCBhbmFseXNlcyB3ZSBjb3ZlcmVkIGR1cmluZyB0aGUgY291cnNlIGFuZCBhaW1zIHRvIGhlbHAgeW91IGNob29zZSBhbW9uZyB0aGVtIGJhc2VkIG9uIHRoZSBuYXR1cmUgb2YgZGVwZW5kZW50IHZhcmlhYmxlcyBvbiB0aGUgc2lkZSwgYW5kIHRoZSBuYXR1cmUgYW5kIHRoZSBudW1iZXIgb2YgeW91ciBpbmRlcGVuZGVudCB2YXJpYWJsZXMgb24gdGhlIG90aGVyIHNpZGU6IA0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoID0gJzkwJScsZmlnLmFsaWduPSdjZW50ZXInfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIm92ZXJ2aWV3LXN0YXRpc3RpY2FsLXRlc3QuanBnIikNCmBgYA0KDQpXaGVuIGl0IGNvbWVzIHRvIHNjYWxpbmcgdGVjaG5pcXVlcywgdGhleSBhcmUgbWVhbnQgdG8gc3R1ZHkgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG9iamVjdHMuIFRoZSBiYXNpYyBzY2FsaW5nIHRlY2huaXF1ZXMgY2xhc3NpZmljYXRpb24gaXMgb24gKipjb21wYXJhdGl2ZSoqIGFuZCAqKm5vbi1jb21wYXJhdGl2ZSBzY2FsZXMqKi4gDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGggPSAnOTAlJyxmaWcuYWxpZ249J2NlbnRlcid9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygic2NhbGVzLnBuZyIpDQpgYGANCg0KKipUaGUgbm9uY29tcGFyYXRpdmUgc2NhbGUqKiBlYWNoIG9iamVjdCBpcyBzY2FsZWQgaW5kZXBlbmRlbnRseSBvZiB0aGUgb3RoZXIgb2JqZWN0cy4gVGhlIHJlc3VsdGluZyBkYXRhIGlzIHN1cHBvc2VkIHRvIGJlIG1lYXN1cmVkIGluIGFuIGludGVydmFsIGFuZCByYXRpbyBzY2FsZWQuDQoNCioqQ29tcGFyYXRpdmUgc2NhbGVzIChvciBub25tZXRyaWMgc2NhbGluZykqKiBjb21wYXJlIGRpcmVjbHR5IHRoZSBzdGltdWx1cyBvYmplY3QuIEZvciBleGFtcGxlLCB0aGUgcmVzcG9uZGVudCBtaWdodCBiZSBhc2tlZCBkaXJlY3RseSBhYm91dCBoaXMgcHJlZmVyZW5jZSBiZXR3ZWVuIGRvbWVzdGljIGFuZCBmb3JlaWduIGJlZXIgYnJhbmRzLiBBcyBhIHJlc3VsdCwgdGhlIGNvbXBhcmF0aXZlIGRhdGEgY29sbGVjdGVkIGNhbiBvbmx5IGJlIGludGVycHJldGVkIGluIHJlbGF0aXZlIHRlcm1zLiBJbiB0aGUgZm9sbG93aW5nIHNlY3Rpb25zIHdlIHdpbGwgd2FsayB0aHJvdWdoIGJvdGggdHlwZXMgb2YgY29tcGFyYXRpdmUgc2NhbGVzIGFuZCBicmllZmx5IGludHJvZHVjZSB0aGVtLg0KDQoNCiMjIyMgQ29tcGFyYXRpdmUgc2NhbGU6IFBhaXJlZCBDb21wYXJpc29uICAgIA0KDQoqIFJlc3BvbmRlbnQgaXMgcHJlc2VudGVkIHdpdGggdHdvIG9iamVjdHMgYW5kIGFza2VkIHRvIHNlbGVjdCBvbmUgYWNjb3JkaW5nIHRvIHNvbWUgY3JpdGVyaW9uLg0KKiBUaGUgbmF0dXJlIG9mIHJlc3VsdGluZyBkYXRhIGlzIG9yZGluYWwNCiogQXNzdW1wdGlvbiBvZiB0cmFuc2l0aXZpdHkgKGlmIFggPiBZIGFuZCBZID4gWiwgdGhlbiBYID4gWikgZW5hYmxlcyB0aGUgcGFpcmVkIGNvbXBhcmlzb24gZGF0YSB0byBiZSBjb252ZXJ0ZWQgaW50byBhIHJhbmsgb3JkZXIuIFRvIGRvIHNvLCB5b3UgbmVlZCB0byBpbmRldGlmeSB0aGUgbnVtYmVyIG9mIHRpbWVzIHRoZSBvYmplY3QgaXMgcHJlZmVycmVkIGJ5IGFkZGluZyB1cCBhbGwgdGhlIG1hdHJpY2VzLg0KKiBFZmZlY3RpdmUgd2hlbiB0aGUgbnVtYmVyIG9mIG9iamVjdHMgaXMgbGltaXRlZCBhcyBpdCByZXF1aXJlcyB0aGUgZGlyZWN0IGNvbXBhcmlzb24sIGFuZCBhIGJpZ2dlciBudW1iZXIgb2Ygb2JqZWN0cyBtYWtlcyB0aGUgY29tcGFyaXNvbiBiZWNvbWVzIHVubWFuYWdhYmxlLg0KKiAqRXhhbXBsZToqICANCkZvciBlYWNoIHBhaXIsIHBsZWFzZSBpbmRpY2F0ZSB3aGljaCBvZiB0aGUgdHdvIGJyYW5kcyBvZiBiZWVyIGluIHRoZSBwYWlyIHlvdSBwcmVmZXIuDQpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9JzkwJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygncGFpcmVkIGNvbXBhcmlzb24ucG5nJykNCmBgYA0KDQojIyMjIENvbXBhcmF0aXZlIHNjYWxlOiBSYW5rIE9yZGVyICANCg0KKiBBbGxvdyBhIGNlcnRhaW4gc2V0IG9mIGJyYW5kcyBvciBwcm9kdWN0cyB0byBiZSBzaW11bHRhbmVvdXNseSByYW5rZWQgYmFzZWQgdXBvbiBhIHNwZWNpZmljIGF0dHJpYnV0ZSBvciBjaGFyYWN0ZXJpc3RpYy4NCiogVGhlIHJhbmsgb3JkZXIgc2NhbGluZyBpcyBhIGdvb2QgcHJveHkgZm9yIHRvIHRoZSBzaG9wcGluZyBzZXR0aW5nIGFzIHRoZXJlIGFyZSBzaW11bHRhbmlvdXMgY29tcGFyaXNvbnMgb2Ygb2JqZWN0cy4NCiogVGhlIHJhbmsgb3JkZXIgc2NhbGluZyByZXN1bHRzIGluIHRoZSBkYXRhIG9mIG9yZGluYWwgbmF0dXJlLg0KKiAqRXhhbXBsZToqICANClJhbmsgdGhlIHZhcmlvdXMgYnJhbmRzIG9mIGJlZXIgaW4gb3JkZXIgb2YgcHJlZmVyZW5jZS4gQmVnaW4gYnkgcGlja2luZyBvdXQgdGhlIG9uZSBicmFuZCB0aGF0IHlvdSBsaWtlIG1vc3QgYW5kIGFzc2lnbiBpdCBhIG51bWJlciAxLiBUaGVuIGZpbmQgdGhlIHNlY29uZCBtb3N0IHByZWZlcnJlZCBicmFuZCBhbmQgYXNzaWduIGl0IGEgbnVtYmVyIDIuIENvbnRpbnVlIHRoaXMgcHJvY2VkdXJlIHVudGlsIHlvdSBoYXZlIHJhbmtlZCBhbGwgdGhlIGJyYW5kcyBvZiBiZWVyIGluIG9yZGVyIG9mIHByZWZlcmVuY2UuDQpObyB0d28gYnJhbmRzIHNob3VsZCByZWNlaXZlZCB0aGUgc2FtZSByYW5rIG51bWJlci4NCg0KYGBge3IsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLG91dC53aWR0aD0nNTAlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCdyYW5rLW9yZGVyLXNjYWxlLnBuZycpDQpgYGANCg0KIyMjIyBDb21wYXJhdGl2ZSBzY2FsZTogQ29uc3RhbnQgc3VtICANCg0KKiBSZXNwb25kZW50cyBhbGxvY2F0ZSBhIGNvbnN0YW50IHN1bSBvZiB1bml0cyAoZS5nLiwgcG9pbnRzLCBkb2xsYXJzKSBhbW9uZyBhIHNldCBvZiBzdGltdWx1cyBvYmplY3RzIHdpdGggcmVzcGVjdCB0byBzb21lIGNyaXRlcmlvbi4gIA0KKiBDb25zdGFudCBzdW0gaXMgc2ltaWxhciB0byByYW5rIG9yZGVyLCBidXQgaXQgY2FycmllcyBzcGVjaWZpYyB1bml0cy4gIA0KKiBUaGUgcmVzdWx0aW5nIGRhdGEgZG9lcyBub3QganVzdCBpbmRpY2F0ZSBpbXBvcnRhbnQgZmFjdG9ycywgYnV0IGFsc28gYnkgaG93IG11Y2ggYSBmYWN0b3Igc3VwZXJzZWRlcyBhbm90aGVyIG9uZS4gIA0KKiBDb25zdGFudCBzdW0gc2NhbGluZyBjYW4gYmUgdXNlZCB0byBvYnNlcnZlIHRoZSBjb21wYXJhdGl2ZSBzaWduaWZpY2FuY2UgcmVzcG9uZGVudHMgYXNzaWduZWQgdG8gdmFyaW91cyBmYWN0b3JzIG9mIGEgc3ViamVjdC4gIA0KKiAqRXhhbXBsZToqICANClRoZXJlIGFyZSA4IGF0dHJpYnV0ZXMgb2YgYm90dGxlZCBiZWVycy4gUGxlYXNlIGFsbG9jYXRlIDEwMCBwb2ludHMgYW1vbmcgdGhlIGF0dHJpYnV0ZXMgc28gdGhhdCB5b3VyIGFsbG9jYXRpb24gcmVmbGVjdHMgdGhlIHJlbGF0aXZlIGltcG9ydGFuY2UgeW91IGF0dGFjaCB0byBlYWNoIGF0dHJpYnV0ZS4NCg0KYGBge3IsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLG91dC53aWR0aD0nODAlJ30NCmtuaXRyOjogaW5jbHVkZV9ncmFwaGljcygnY29uc3RhbnQtc3VtLXNjYWxlLnBuZycpDQpgYGANCg0KKiBCYXNpYyBhbmFseXNpcyBvZiBjb25zdGFudC1zdW0gZGF0YSBpbnZvbHZlcyB0YWJ1bGF0aW9uIG9mIHJlc3BvbnNlcyBhbmQgcHJlc2VudGluZyB0aGVtIGFzIGVpdGhlciBxdWFudGl0aWVzIChlLmcuLCAib24gYXZlcmFnZSwgNyBwb2ludHMgd2VyZSBhbGxvY2F0ZWQgdG8gImhpZ2ggYWxjb2hvbCBsZXZlbCIpLCBvciwgYXMgcHJvcG9ydGlvbnMgKCJPbiBhdmVyYWdlLCA3JSBvZiBwb2ludHMgd2VyZSBhbGxvY2F0ZWQgdG8gImhpZ2ggYWxjb2hvbCBsZXZlbCIpLiAgDQoNCg0KIyMjIyBOb24tQ29tcGFyYXRpdmUgU2NhbGVzOiBDb250aW51b3VzIFJhdGluZyBTY2FsZXMgIA0KDQoqIFBhcnRpY2lwYW50cyByYXRlIHRoZSBvYmplY3RzIGJ5IHBsYWNpbmcgYSBtYXJrIGF0IHRoZSBhcHByb3ByaWF0ZSBwb3NpdGlvbiBvbiBhIGxpbmUgdGhhdCBydW5zIGZyb20gb25lIGV4dHJlbWUgb2YgdGhlIGNyaXRlcmlvbiB2YXJpYWJsZSB0byB0aGUgb3RoZXIuICANCiogT25lIG9mIHRoZSBhZHZhbnRhZ2VzIG9mIHRoZSBjb250aW51b3VzIHJhdGluZyBzY2FsZSBpcyB0aGF0IGl0IGlzIGVhc3kgdG8gYWRtaW5pc3Rlci4gIA0KDQpgYGB7ciwgZWNobz1GLCBmaWcuYWxpZ249J2NlbnRlcicsb3V0LndpZHRoPSc3MCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ2NvbnRpbnVvdXMtcmF0aW5nLXNjYWxlLnBuZycpDQpgYGANCg0KKiBPbmNlIHRoZSByYXRpbmdzIGFyZSBjb2xsZWN0ZWQsIHlvdSBjYW4gc3BsaXRzIHVwIHRoZSBvYnRhaW5lZCByYXRpbmdzIGludG8gY2F0ZWdvcmllcyBhbmQgdGhlbiBhc3NpZ24gdGhvc2UgZGVwZW5kaW5nIG9uIHRoZSBjYXRlZ29yeSBpbiB3aGljaCB0aGUgcmF0aW5ncyBmYWxsLg0KDQoNCiMjIyMgTm9uLUNvbXBhcmF0aXZlIFNjYWxlczogSXRlbWl6ZWQgUmF0aW5nIFNjYWxlcyAgDQoNCiogVGhlIHJlc3BvbmRlbnRzIGFyZSBwcm92aWRlZCB3aXRoIGEgc2NhbGUgdGhhdCBoYXMgYSBudW1iZXIgb3IgYnJpZWYgZGVzY3JpcHRpb24gYXNzb2NpYXRlZCB3aXRoIGVhY2ggY2F0ZWdvcnkuICANCiogVGhlIGNhdGVnb3JpZXMgYXJlIG9yZGVyZWQgaW4gdGVybXMgb2Ygc2NhbGUgcG9zaXRpb24sIGFuZCB0aGUgcmVzcG9uZGVudHMgYXJlIHJlcXVpcmVkIHRvIHNlbGVjdCB0aGUgc3BlY2lmaWVkIGNhdGVnb3J5IHRoYXQgYmVzdCBkZXNjcmliZXMgdGhlIG9iamVjdCBiZWluZyByYXRlZC4gIA0KKiBUaGUgY29tbW9ubHkgdXNlZCBpdGVtaXplZCByYXRpbmcgc2NhbGVzIGFyZSAqKnRoZSBMaWtlcnQsIHNlbWFudGljIGRpZmZlcmVudGlhbCBhbmQgU3RhcGVsIHNjYWxlcy4qKg0KDQojIyMjIyBJdGVtaXplZCBSYXRpbmcgU2NhbGVzOiAgTGlrZXJ0IHNjYWxlDQoNCiogUmVxdWlyZXMgcmVzcG9uZGVudHMgdG8gaW5kaWNhdGUgdGhlaXIgYXR0aXR1ZGUgdG93YXJkcyB0aGUgZ2l2ZW4gb2JqZWN0IHRocm91Z2ggdGhlIGRlZ3JlZSBvZiBhZ3JlZW1lbnQgb3IgZGlzYWdyZWVtZW50IHdpdGggZWFjaCBvZiBhIHNlcmllcyBvZiBzdGF0ZW1lbnRzIHdpdGhpbiB0eXBpY2FsbHkgZml2ZSBvciBzZXZlbiBjYXRlZ29yaWVzLiAgDQoqIFJldmVyc2VkIGNvZGUgb2Ygc29tZSBpdGVtcyBpbmNyZWFzZXMgdmFsaWRpdHkuICANCiogT25lIGxpbWl0YXRpb24gaXMgdGltZSByZXF1aXJlZCB0byBhbnN3ZXIgYSBxdWVzdGlvbiBvbiBhIExpa2VydCBzY2FsZS4gQ29tcGFyZWQgdG8gb3RoZXIgaXRlbWl6ZWQgc2NhbGluZyB0ZWNobmlxdWVzLCBMaWtlcnQgc2NhbGUgaXMgbW9yZSB0aW1lIGNvbnN1bWluZyBhcyBlYWNoIHJlc3BvbmRlbnQgaXMgcmVxdWlyZWQgdG8gcmVhZCBldmVyeSBzdGF0ZW1lbnQgZ2l2ZW4gaW4gYSBxdWVzdGlvbm5haXJlIGJlZm9yZSBhc3NpZ25pbmcgYSBudW1lcmljYWwgdmFsdWUgdG8gaXQuDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzcwJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnbGlrZXJ0LnBuZycpDQpgYGANCg0KSW4gdGhlIHRhYmxlIGJlbG93IHlvdSBjYW4gZmluZCBhIGNvdXBsZSBvZiBjb21tb25seSBtZWFzdXJlZCBjb25zdHJ1Y3RzIGluIG1hcmtldGluZyByZXNlYXJjaCBzdWNoIGFzIGF0dGl0dWRlLCBpbXBvcnRhbmNlLCBwdXJjaGFzZSBpbnRlbnRpb24gYW5kIHNpbWlsYXIuDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzcyJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnbGlrZXJ0LW1hcmtldGluZy1yZXNlcmFjaC5wbmcnKQ0KYGBgDQoNCg0KIyMjIyMgSXRlbWl6ZWQgUmF0aW5nIFNjYWxlczogU2VtYW50aWMgRGlmZmVyZW50aWFsDQoNCiogVHlwaWNhbGx5LCBwYXJ0aWNpcGFudHMgcmF0ZSBvYmplY3RzIG9uIGEgbnVtYmVyIG9mIGl0ZW1pemVkLCBzZXZlbi1wb2ludCByYXRpbmcgc2NhbGVzIGJvdW5kZWQgYXQgZWFjaCBlbmQgYnkgb25lIG9mIHR3byBiaXBvbGFyIGFkamVjdGl2ZXMuICANCg0KKiBTZW1hbnRpYyBkaWZmZXJlbnRpYWwgY2FuIG1lYXN1cmUgcmVzcG9uZGVudCBhdHRpdHVkZXMgdG93YXJkcyBzb21ldGhpbmcgKHByb2R1Y3RzLGNvbmNlcHRzLCBpdGVtcywgcGVvcGxlLi4uKS4NCg0KKiBJdCBoZWxwcyB5b3UgZmluZCB0aGUgcmVwb25kZW50J3MgcG9zaXRpb24gaXMgb24gYSBzY2FsZSBiZXR3ZWVuIHR3byBiaXBvbGFyIGFkamVjdGl2ZXMgc3VjaCBhcyDigJxTd2VldC1Tb3Vy4oCdIG9yIOKAnEJyaWdodC1EYXJr4oCdLiBJbiBjb21wYXJpc29uIHRvIExpa2VydCBzY2FsZSwgd2hpY2ggdXNlcyBnZW5lcmljIHNjYWxlcyAoZS5nLiBleHRyZW1lbHkgZGlzc2F0aXNmaWVkIHRvIGV4dHJlbWVseSBzYXRpc2ZpZWQpLCBzZW1hbnRpYyBkaWZmZXJlbnRpYWwgcXVlc3Rpb25zIGFyZSBwb3NlZCB3aXRoaW4gdGhlIGNvbnRleHQgb2YgZXZhbHVhdGluZyBhdHRpdHVkZXMuDQoNCiogV2lkZWx5IHVzZWQgcmF0aW5nIHNjYWxlIGluIG1hcmtldGluZyByZXNlYXJjaCBkdWUgdG8gaXRzIHZlcnNhdGlsaXR5DQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzcyJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnc2VtYW50aWMtZGlmZmVyZW50aWFsLnBuZycpDQpgYGANCg0KV2hlbiBjcmVhdGluZyBhIHNlbWFudGljYWwgZGlmZmVyZW5jZSBxdWVzdGlvbiwgeW91IHNob3VsZCBjb25zaWRlciB0aGUgZm9sbG93aW5nOg0KDQoqICoqTnVtYmVyIG9mIGNhdGVnb3JpZXM6KiogDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nbGVmdCcsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ3NlbWFudGljLWRpZmZlcmVudGlhbC0xLnBuZycpDQpgYGANCg0KKiAqKkJhbGFuY2VkIHZzLiB1bmJhbGFuY2VkOioqDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nbGVmdCcsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ3NlbWFudGljLWRpZmZlcmVudGlhbC0yLnBuZycpDQpgYGANCg0KKiAqKk9kZC9ldmVuIG51bWJlciBvZiBjYXRlZ29yaWVzOioqDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nbGVmdCcsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ3NlbWFudGljLWRpZmZlcmVudGlhbC0zLnBuZycpDQpgYGANCg0KKiAqKkZvcmNlZCB2cy4gbm9uLWZvcmNlZCByZXNwb25zZSoqDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nbGVmdCcsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ3NlbWFudGljLWRpZmZlcmVudGlhbC00LnBuZycpDQpgYGANCg0KKiAqKlZlcmJhbCBkZXNjcmlwdGlvbjoqKg0KDQpgYGB7ciwgZWNobz1GLCBmaWcuYWxpZ249J2xlZnQnLG91dC53aWR0aD0nNzIlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCdzZW1hbnRpYy1kaWZmZXJlbnRpYWwtNS5wbmcnKQ0KYGBgDQoNCg0KDQoNCg0KIyMjIFF1ZXN0aW9ubmFpcmUgc3RydWN0dXJlDQoNClRoZSBzZXF1bmVjZSBvZiBxdWVzdGlvbnMgaW4gYSBxdWVzdGlvbm5haXJlIGNvdWxkIHBsYXkgaW1wb3JhbnQgcm9sZS4gRm9yIGluc3RhbmNlLCBtb3JlIHNlbnNpdGl2ZSBxdWVzdGlvbnMgKHN1Y2ggYXMgZGVtb2dyYXBoaWMtcmVsYXRlZCBxdWVzdGlvbnMpIGFyZSB1c3VhbGx5IHBsYWNlZCBhdCB0aGUgZW5kIGFzIHRoZXkgY2FuIHRyaWdnZXIgY2hhbmdlIGluIHJlc3BvbmRlbnQncyBiZWhhdmlvci4gDQoNCklmIHlvdSBwbGFuIHRvIGNvbmR1Y3QgYW4gb25saW5lIHN1cnZleSwgdGhlbiB5b3UgbmVlZCB0byB0aGluayBhYm91dCB0aGUgcmVzcG9uZGVudCdzIGV4cGVyaWVuY2Ugd2hpbGUgZG9pbmcgeW91ciBxdWVzdGlvbm5haXJlLiBGb3IgaW5zdGFuY2UsIHNwcmVhZCB0aGUgY29udGVudCBvdmVyIG1vcmUgc2hvcnQgcGFnZXMgYW5kIGRvIG5vdCBoYXZlIGZld2VyIGxvbmcgcGFnZXMuIEluIG9ubGluZSBzdXJ2ZXlzLCB0d28gcXVlc3Rpb25zIG9uIG9uZSBwYWdlIGlzIGEgdXNlZnVsIHJ1bGUgb2YgdGh1bWIuIEdlbmVyYWxseSwgcmVzcG9uZGVudHMgYXJlIHJlbHVjdGFudCB0byByZWFkIGFuZCBmaWxsIG91dCBsb25nIHF1ZXN0aW9ubmFpcmUgcGFnZXMuIEhlbmNlLCBsb25nIHBhZ2VzIHdpbGwgbGVhZCB0byBhIGhpZ2hlciBkcm9wb3V0IHJhdGUuDQpJbiBvcmRlciB0byByZWR1Y2UgZHJvcG91dCByYXRlIHN0YXRlIGhvdyBsb25nIHRoZSBzdXJ2ZXkgd2lsbCBhcHByb3hpbWF0ZWx5IHRha2UgaW4gdGhlIGludHJvZHVjdGlvbiBvZiB0aGUgcXVlc3Rpb25uYWlyZS4gVGFrZSBpbnRvIGFjY291bnQgdGhhdCB0b29scyBsaWtlIFF1YWx0cmljcyBwcm92aWRlIHRoZSBlc3RpbWF0ZWQgcmVzcG9uc2UgdGltZSBpbiB0aGUgc3VydmV5IG92ZXJ2aWV3Lg0KDQpDb25zaWRlciB0aGF0IHRoZSBtb3N0IG9mIHBlb3BsZSB1c3VhbGx5IHVzZSB0aGVpciBwaG9uZXMgdG8gZmlsbCBpdCBvdXQuIFRoaW5rIGFib3V0IGhvdyB0aGUgcXVlc3Rpb25uYWlyZSB3aWxsIGFwcGVhciBvbiBhIHBob25lIHNjcmVlbiB0b28uIEluIHRoYXQgcmVnYXJkLCB0aGluayBvZiBsZW5ndGggb2YgcXVlc3Rpb25zIGVzcGVjaWFsbHkuDQoNCkluIHRoZSBlbmQsIHRoZSBxdWVzdGlvbm5haXJlIHN0cnVjdHVyZSBoYXMgdG8gYmUgYWxpZ25lZCB3aXRoIHRoZSByZXNlYXJjaCBkZXNpZ24uIEZvciBleGFtcGxlLCBpZiB5b3VyIHJlc2VhcmNoIGRlc2lnbiBmZWF0dXJlcyBhbiBleHBlcmltZW50LCB0aGlzIG5lZWRzIHRvIGJlIHJlZmxlY3RlZCBpbiB0aGUgcXVlc3Rpb25uYWlyZSAoZS5nLiwgeW91IG5lZWQgdG8gYXNzaWduIHRoZSByZXNwb25kZW50cyByYW5kb21seSB0byB0aGUgZXhwZXJpbWVudGFsIGNvbmRpdGlvbnMgaW4gY2FzZSBvZiBhIGJldHdlZW4tc3ViamVjdHMgY29tcGFyaXNvbikuDQoNCiMjIyMgUXVlc3Rpb25uYWlyZSBzdHJ1Y3R1cmUgZm9yIGEgYmV0d2Vlbi1zdWJqZWN0cyBkZXNpZ24NCg0KSW4gYSBiZXR3ZWVuLXN1YmplY3QgZGVzaWduIHlvdSByYW5kb21seSBhc3NpZ24gZWFjaCByZXNwb25kZW50IHRvIGRpZmZlcmVudCBleHBlcmltZW50YWwgY29uZGl0aW9ucy4gVGhleSB3b3VsZCB0aGVuIGNvbXBsZXRlIHRhc2tzIG9ubHkgaW4gdGhlIGNvbmRpdGlvbiB0byB3aGljaCB0aGV5IGFyZSBhc3NpZ25lZC4NCg0KRm9yIGluc3RhbmNlLCB3ZSB3b3VsZCBsaWtlIHRvIHRlc3QgdGhlIGVmZmVjdCBvZiB0d28gYWR2ZXJ0aXNlbWVudHMgb24gcHVyY2hhc2UgaW50ZW50aW9uLiBUaGVyZWZvcmUsIG9uZSBncm91cCBvZiAocmFuZG9tbHkgYXNzaWduZWQpIHJlc3BvbmRlbnRzIHdpbGwgYmUgZXhwb3NlZCB0byBvbmUgYWR2ZXJ0aXNlbWVudCB2ZXJzaW9uIHdoaWxlIHRoZSBvdGhlciBncm91cCAob2YgcmFuZG9tbHkgYXNzaWduZWQgcmVzcG9uZGVudHMpIHdpbGwgYmUgZXhwb3NlZCB0byBhbm90aGVyIHZlcnNpb24uIEFmdGVyIHRoYXQsIGJvdGggZ3JvdXBzIG9mIHJlc3BvbmRlbnRzIHNob3VsZCBleHByZXNzIHRoZWlyIHdpbGxpbmduZXNzIHRvIGJ1eSB0aGUgYWR2ZXJ0aXNlZCBwcm9kdWN0LiBFdmVudXRhbGx5LCBpZiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChlLmcuIHdpbGxpbmduZXNzIHRvIGJ1eSkgaXMgbWVhc3VyZWQgb24gaW50ZXJ2YWwgb3IgcmF0aW8gc2NhbGUsIHRoZW4geW91IGNhbiB1c2UgaW5kZXBlbmRlbnQgdC10ZXN0IHRvIGNvbXBhcmUgZ3JvdXAgbWVhbnMuIFRoZSB3aG9sZSBleHBlcmltZW50YWwgZGVzaWduIHNob3VsZCBiZSBvcmdhbmlzZWQgYXMgZm9sbG93aW5nOg0KDQpgYGB7ciwgZWNobz1GLCBmaWcuYWxpZ249J2NlbnRlcicsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ2JldHdlZW4tc3ViamVjdC1kZXNpZ24ucG5nJykNCmBgYA0KDQoNCiMjIyMgUXVlc3Rpb25uYWlyZSBzdHJ1Y3R1cmUgZm9yIGEgd2l0aGluLXN1YmplY3RzIGRlc2lnbg0KDQpUaGlzIHR5cGUgb2YgZXhwZXJpbWVudGFsIGRlc2lnbiBpbnZvbHZlcyBleHBvc2luZyBlYWNoIHJlc3BvbmRlbnQgdG8gYWxsIG9mIHRoZSB1c2VyIGV4cGVyaW1lbnRhbCBjb25kaXRpb25zIHlvdeKAmXJlIHRlc3RpbmcuIFRoaXMgd2F5LCBlYWNoIHJlc3BvbmRlbnQgd2lsbCB0ZXN0IGFsbCBvZiB0aGUgY29uZGl0aW9ucy4NCg0KRm9yIGluc3RhbmNlLCB3ZSB3b3VsZCBsaWtlIHRvIHRlc3QgYWdhaW4gdGhlIGVmZmVjdCBvZiB0d28gYWR2ZXJ0aXNlbWVudHMgb24gcHVyY2hhc2UgaW50ZW50aW9ucywgYnV0IHRoaXMgdGltZSBpbiBhIHdpdGhpbi1zdWJqZWN0IGRlc2lnbi4gRmlyc3QsIGVhY2ggcmVzcG9uZGVudCB3aWxsIGJlIGV4cG9zZWQgdG8gdGhlIGZpcnN0IHZlcnNpb24gb2YgYWR2ZXJ0aXNlbWVudCBhbmQgcmlnaHQgYWZ0ZXIgdGhhdCBhc2tlZCB0byByYXRlIGhpcy9oZXIgd2lsbGluZ25lc3MgdG8gYnV5IHRoZSBhZHZlcnRpc2VkIHByb2R1Y3QuIFN1YnNlcXVlbnRseSwgZWFjaCBwYXJ0aWNpcGFudCB3aWxsIGJlIHNob3duIGFub3RoZXIgdmVyc2lvbiBvZiBhZHZlcnRpc2VtZW50IGFuZCBhZ2FpbiByYXRlIGhpcy9oZXIgd2lsbGluZ25lc3MgdG8gcHVyY2hhc2UgdGhlIGFkdmVydGlzZWQgcHJvZHVjdC4gRmluYWxseSwgd2UgY2FuIGNvbXBhcmUgZ3JvdXAgbWVhbnMgd2l0aCBwYWlyZWQgc2FtcGxlIHQtdGVzdCAoZ2l2ZW4gdGhhdCBkYXRhIGlzIG1lYXN1cmVkIG9uIGludGVydmFsIG9yIHJhdGlvIHNjYWxlKS4gDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzcyJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnd2l0aGluLXN1YmplY3QtZGVzaWduLnBuZycpDQpgYGANCg0KDQojIyMgUXVlc3Rpb24gd29yZGluZw0KDQpHZW5lcmFsbHksIHF1ZXN0aW9uIHdvcmRpbmcgc2hvdWxkIGVuYWJsZSBlYWNoIHJlc3BvbmRlbnQgdG8gdW5kZXJzdGFuZCAgcXVlc3Rpb25zIGFuZCB0byBiZSBhYmxlIHRvIGFuc3dlciB0aGVtIHdpdGggcmVsaWFiaWxpdHkuIFJlbGlhYmlsaXR5IG1lYW5zIHRoYXQsIGlmIGEgcmVzcG9uZGVudCB3YXMgYXNrZWQgdGhlIHNhbWUgcXVlc3Rpb24gYWdhaW4sIGhlL3NoZSB3b3VsZCBnaXZlIHRoZSBzYW1lIGFuc3dlciBhZ2Fpbi4gQSBudW1iZXIgb2YgY29tbW9uIHByb2JsZW1zIHJlZ2FyZGluZyB0aGUgcXVlc3Rpb24gd29yZGluZyBoYXZlIGJlZW4gaWRlbnRpZmllZCwgc28gd2Ugd2lsbCBhZGRyZXNzIHRoZSBtb3N0IGltcG9ydGFudCBvbmVzLiANCg0KSW4gb3JkZXIgdG8gZW5zdXJlIHJlbGlhYmlsaXR5LCB0aGUgaXNzdWUgaW4gdGVybXMgb2YgKip3aG8sIHdoYXQsIHdoZW4gYW5kIHdoZXJlKiogc2hvdWxkIGJlIGRlZmluZWQgaW4gZWFjaCBxdWVzdGlvbi4gIA0KKkV4YW1wbGU6KiBXaGljaCBicmFuZCBvZiBzaGFtcG9vIGRvIHlvdSB1c2U/ICANCioqV2hvICh0aGUgcmVzcG9uZGVudCk6KiogSXQgaXMgbm90IGNsZWFyIHdoZXRoZXIgdGhpcyBxdWVzdGlvbiByZWxhdGVzIHRvIHRoZSBpbmRpdmlkdWFsIHJlc3BvbmRlbnQgb3IgdGhlIHJlc3BvbmRlbnTigJlzIHRvdGFsIGhvdXNlaG9sZC4gIA0KKipXaGF0ICh0aGUgYnJhbmQgb2Ygc2hhbXBvbyk6KiogSXQgaXMgdW5jbGVhciBob3cgdGhlIHJlc3BvbmRlbnQgaXMgdG8gYW5zd2VyIHRoaXMgcXVlc3Rpb24gaWYgbW9yZSB0aGFuIG9uZSBicmFuZCBpcyB1c2VkLiAgDQoqKldoZW4gKHVuY2xlYXIpOioqIFRoZSB0aW1lIGZyYW1lIGlzIG5vdCBzcGVjaWZpZWQgaW4gdGhpcyBxdWVzdGlvbi4gVGhlIHJlc3BvbmRlbnQgY291bGQgaW50ZXJwcmV0IGl0IGFzIG1lYW5pbmcgdGhlIHNoYW1wb28gdXNlZCB0aGlzIG1vcm5pbmcsIHRoaXMgd2Vlaywgb3Igb3ZlciB0aGUgcGFzdCB5ZWFyLiAgDQoqKldoZXJlIChub3Qgc3BlY2lmaWVkKToqKiBBdCBob21lLCBhdCB0aGUgZ3ltPyBXaGVyZT8NCg0KKkEgbW9yZSBjbGVhcmx5IGRlZmluZWQgcXVlc3Rpb24gaXM6KiAgDQpXaGljaCBicmFuZCBvciBicmFuZHMgb2Ygc2hhbXBvbyBoYXZlIHlvdSBwZXJzb25hbGx5IHVzZWQgYXQgaG9tZSBkdXJpbmcgdGhlIGxhc3QgbW9udGg/IEluIHRoZSBjYXNlIG9mIG1vcmUgdGhhbiBvbmUgYnJhbmQsIHBsZWFzZSBsaXN0IGFsbCB0aGUgYnJhbmRzIHRoYXQgYXBwbHkuDQoNCioqVXNlIG9yZGluYXJ5IHdvcmRzLioqIFdvcmRzIHNob3VsZCBtYXRjaCB0aGUgdm9jYWJ1bGFyeSBsZXZlbCBvZiB0aGUgcGFydGljaXBhbnRzLiAgDQo8c3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiPjxCPkluY29ycmVjdDo8L0I+PC9zcGFuPiAgICANCuKAnERvIHlvdSB0aGluayB0aGUgZGlzdHJpYnV0aW9uIG9mIHNvZnQgZHJpbmtzIGlzIGFkZXF1YXRlP+KAnSAgIA0KPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPjxCPkNvcnJlY3Q6PC9CPjwvc3Bhbj4gIA0K4oCcRG8geW91IHRoaW5rIHNvZnQgZHJpbmtzIGFyZSBlYXNpbHkgYXZhaWxhYmxlIHdoZW4geW91IHdhbnQgdG8gYnV5IHRoZW0/4oCdDQoNCioqQXZvaWQgZG91YmxlIG5lZ2F0aXZlIGZvcm0qKi4gRG91YmxlIG5lZ2F0aXZlIHF1ZXN0aW9uIGZvcm1zIGNhbiBjb25mdXNlIHJlc3BvbmRlbnRzLCBlc3BlY2lhbGx5IHdoZW4gdGhleSBuZWVkIHRvIGFuc3dlciB3aXRoIOKAnEFncmVl4oCdIG9yIOKAnERpc2FncmVl4oCdLg0KDQo8c3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiPjxCPkluY29ycmVjdDo8L0I+PC9zcGFuPiAgICAgIA0KRG8geW91IHRoaW5rIHRoYXQgaXQgaXMgbm90IHVuY29tbW9uIHRoYXQgYm95cyBwbGF5IGJhc2tldGJhbGw/ICANCjxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij48Qj5Db3JyZWN0OjwvQj48L3NwYW4+ICANCkluIHlvdXIgb3BpbmlvbiwgaXMgaXQgY29tbW9uIHRoYXQgYm95cyBwbGF5IGJhc2tldGJhbGw/DQoNCg0KDQoqKkF2b2lkIGxlYWRpbmcgcXVlc3Rpb25zLioqTGVhZGluZyBxdWVzdGlvbnMgY2x1ZSB0aGUgcGFydGljaXBhbnQgdG8gd2hhdCB0aGUgYW5zd2VyIHNob3VsZCBiZS4gU3VjaCBxdWVzdGlvbnMgaW50cm9kdWNlIGEgYmlhcyBpbiBhIHBhcnRpY3VsYXIgZGlyZWN0aW9uLiAgDQo8c3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiPjxCPkluY29ycmVjdDo8L0I+PC9zcGFuPiAgICANCuKAnElzIENvbGdhdGUgeW91ciBmYXZvcml0ZSB0b290aHBhc3RlP+KAnSAgDQo8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+PEI+Q29ycmVjdDo8L0I+PC9zcGFuPiAgICAgICANCuKAnFdoYXQgaXMgeW91ciBmYXZvcml0ZSBicmFuZCBvZiB0b290aHBhc3RlP+KAnQ0KDQoqKkF2b2lkIGFtYmlndW91cyB3b3Jkcy4qKiBXb3JkcyBzdWNoIGFzIHVzdWFsbHksIG5vcm1hbGx5LCBmcmVxdWVudGx5LCBvZnRlbiwgcmVndWxhcmx5LCBhbmQgb3RoZXIgc2ltaWxhciB3b3JkcywgZG8gbm90IGRlZmluZSBmcmVxdWVuY3kgY2xlYXJseSBlbm91Z2guDQoNCjxzcGFuIHN0eWxlPSJjb2xvcjogcmVkOyI+PEI+SW5jb3JyZWN0OjwvQj48L3NwYW4+ICAgICAgDQrigJxJbiBhIHR5cGljYWxseSBtb250aCwgaG93IG9mdGVuIGRvIHlvdSBnbyB0byBhIG1vdmllIHRoZWF0ZXIgdG8gc2VlIGEgbW92aWU/4oCdICANCmEpIE5ldmVyICANCmIpIE9jY2FzaW9uYWxseSAgDQpjKSBTb21ldGltZXMgICANCmQpIE9mdGVuICAgDQplKSBSZWd1bGFybHkgIA0KDQo8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+PEI+Q29ycmVjdDo8L0I+PC9zcGFuPiAgICAgDQoiSW4gYSB0eXBpY2FsbHkgbW9udGgsIGhvdyBvZnRlbiBkbyB5b3UgZ28gdG8gYSBtb3ZpZSB0aGVhdGVyIHRvIHNlZSBhIG1vdmllPyIgICAgDQphKSBMZXNzIHRoYW4gb25jZSAgDQpiKSAxIG9yIDIgdGltZXMgIA0KYykgMyBvciA0IHRpbWVzICANCmQpIE1vcmUgdGhhbiA0IHRpbWVzDQoNCiMjIyBDaG9vc2UgYWRlcXVhdGUgb3JkZXINCg0KT25lIG9mIHRoZSBsYXN0IHN0ZXBzIGluIGEgcHJvY2VzcyBvZiBkZXNpZ25pbmcgYSBxdWVzdGlvbm5haXJlIGlzIGNob29zaW5nIGFkZXF1YXRlIG9yZGVyIG9mIHF1ZXN0aW9ucyBhbmQgaW5zdHJ1Y3Rpb25zIGZvciByZXNwb25kZW50cy4gDQoNCkF0IHRoZSBiZWdpbmluZywgeW91IHNob3VsZCBwcm92aWRlIGEgc2hvcnQgYW5kIGVhc3ktdG8tdW5kZXJzdGFuZCBpbnRyb2R1Y3Rpb24gdG8gdGhlIHRvcGljLiBVc2Ugc2ltcGxlIGxhbmd1YWdlIGFuZCBhdm9pZCB0ZWNobmljYWwgdGVybXMgKGUuZy4sIG5vdCBtYW55IHBlb3BsZSB3aWxsIGtub3cgdGhlIHRlcm1zIOKAnG1hbnVmYWN0dXJlciBicmFuZOKAnSBhbmQg4oCcc3RvcmUgYnJhbmTigJ0pLiBBZGRpdGlvbmFsbHksIGluIHRoZSBpbnRyb2R1Y3Rpb24geW91IHNob3VsZCBzdGF0ZSBob3cgbG9uZyB0aGUgc3VydmV5IHdpbGwgYXBwcm94aW1hdGVseSB0YWtlLg0KDQpUaGUgb3BlbmluZyBxdWVzdGlvbnMgc2hvdWxkIGJlIGludGVyZXN0aW5nLCBzaW1wbGUgYW5kIG5vbi10aHJlYXRlbmluZy4NClRoZXkgYXJlIGNydWNpYWwgYmVjYXVzZSBpdCBpcyB0aGUgcmVzcG9uZGVudCdzIGZpcnN0IGV4cG9zdXJlIHRvIHRoZSBxdWVzdGlvbm5haXJlIGFuZCBpcyBsaWtlbHkgdG8gc2V0IHRoZSB0b25lIGZvciB0aGUgcmVzdCBvZiBxdWVzdGlvbnMgaW4gdGhlIHF1ZXN0aW9ubmFpcmUuIElmIHRvbyBkaWZmaWN1bHQgdG8gdW5kZXJzdGFuZCwgb3Igc2Vuc2l0aXZlIGluIHNvbWUgd2F5LCByZXNwb25kZW50cyBhcmUgbGlrZWx5IHRvIHN0b3AgYW5zd2VyaW5nIHlvdXIgcXVlc3Rpb25zLiBRdWFsaWZ5aW5nIHF1ZXN0aW9ucyAob3Igc2NyZWVuaW5nIHF1ZXN0aW9ucykgc2hvdWxkIHNlcnZlIGFzIHRoZSBvcGVuaW5nIHF1ZXN0aW9ucyAoaWYgYXBwbGljYWJsZSkuIFRoZWlyIHB1cnBvc2UgaXMgdG8gaWRlbnRpZnkgYSBwb3RlbnRpYWwgcmVzcG9uZGVudCB0aGF0IGlzIGVsaWdhYmxlIHRvIHByb2NlZWQgd2l0aCB0aGUgcmVzZWFyY2ggc3VydmV5Lg0KDQpBZnRlciB0aGUgb3BlbmluZyBwYXJ0LCB5b3Ugc2hvdWxkIGVzdGFibGlzaCBhbiBvcHRpbWFsIHF1ZXN0aW9uIGZsb3cuDQpHZW5lcmFsIHF1ZXN0aW9ucyBzaG91bGQgcHJlY2VkZSB0aGUgc3BlY2lmaWMgcXVlc3Rpb25zLiBRdWVzdGlvbnMgb24gb25lIHN1YmplY3QsIG9yIG9uZSBwYXJ0aWN1bGFyIGFzcGVjdCBvZiBhIHN1YmplY3QsIHNob3VsZCBiZSBncm91cGVkIHRvZ2V0aGVyLiBJdCBtYXkgZmVlbCBjb25mdXNpbmcgdG8gYmUgYXNrZWQgdG8gcmV0dXJuIHRvIHNvbWUgc3ViamVjdCB0aGV5IHRob3VnaHQgdGhleSBhbHJlYWR5IGdhdmUgdGhlaXIgb3BpbmlvbnMgYWJvdXQuDQoNCkFzIHJlc3BvbmRlbnRzIGFyZSBtb3ZpbmcgdG93YXJkcyB0aGUgZW5kIG9mIHRoZSBxdWVzdGlvbm5haXJlLCB0aGV5IGFyZSBsaWtlbHkgdG8gYmVjb21lIGluY3JlYXNpbmdseSBpbmRpZmZlcmVudCBhbmQgbWlnaHQgZ2l2ZSBjYXJlbGVzcyBhbnN3ZXJzLiBUaGVyZWZvcmUsIHF1ZXN0aW9ucyBvZiBzcGVjaWFsIGltcG9ydGFuY2Ugc2hvdWxkIGlkZWFsbHkgYmUgaW5jbHVkZWQgaW4gdGhlIGVhcmxpZXIgcGFydCBvZiB0aGUgcXVlc3Rpb25uYWlyZS4gDQoNCkZpbmFsbHksIHlvdSBzaG91bGQgcGF5IHBhcnRpY3VsYXIgYXR0ZW50aW9uIHRvIHByb3ZpZGUgYWxsIHByZXNjcmliZWQgZGVmaW5pdGlvbnMgYW5kIGV4cGxhbmF0aW9ucyBiZWZvcmUgeW91IGFzayBhIHF1ZXN0aW9uLiBUaGlzIGVuc3VyZXMgdGhhdCB0aGUgcXVlc3Rpb25zIGFyZSB1bmRlc3Rvb2QgaW4gY29uc2lzdGVudCB3YXkgYnkgZXZlcnkgcmVzcG9uZGVudC4NCg0KIyMjIFRlc3QgeW91ciBxdWVzdGlvbm5haXJlDQoNCkZpbmFsbHksIGJlZm9yZSB5b3UgZGlzdHJpYnV0ZSB0aGUgZmluYWwgcXVlc3Rpb25uYWlyZSwgdGhlcmUgYXJlIHNvbWUgdGhpbmdzIHRvIGNvbnNpZGVyLiBGaXJzdCwgeW91IHNob3VsZCBhbHdheXMgcHJldGVzdCB5b3VyIHF1ZXN0aW9ubmFpcmUgYmVmb3JlIHNoYXJpbmcgaXQhDQpUZXN0IGFsbCBhc3BlY3RzIG9mIHRoZSBxdWVzdGlvbm5haXJlIChjb250ZW50LCB3b3JkaW5nLCBzZXF1ZW5jZSwgZm9ybSAmIGxheW91dCwgZXRjLikuIElmIHBvc3NpYmxlLCB1c2UgcmVzcG9uZGVudHMgaW4gdGhlIHByZXRlc3QgdGhhdCBhcmUgc2ltaWxhciB0byB0aG9zZSB3aG8gd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgYWN0dWFsIHN1cnZleS4gSWRlYWxseSwgdGhlIHByZXRlc3Qgc2FtcGxlIHNpemUgc2hvdWxkIGJlIHNtYWxsIChpbiBhIHJlYWwgc2NlbmFyaW8gdGhpcyBjb3VsZCB2YXJ5ZnJvbSAxNSB0byAzMCByZXNwb25kZW50czsgZm9yIHRoZSBncm91cCBwcm9qZWN0LCBhIGxvd2VyIG51bWJlciB3aWxsIGJlIHN1ZmZpY2llbnQpLiBBZnRlciBlYWNoIHNpZ25pZmljYW50IHJldmlzaW9uIG9mIHRoZSBxdWVzdGlvbm5haXJlLCBjb25kdWN0IGFub3RoZXIgcHJldGVzdCwgdXNpbmcgYSBkaWZmZXJlbnQgc2FtcGxlIG9mIHJlc3BvbmRlbnRzLiBFdmVudHVhbGx5LCBjb2RlIGFuZCBhbmFseXplIHRoZSByZXNwb25zZXMgb2J0YWluZWQgZnJvbSB0aGUgcHJldGVzdCBzbyB0aGF0IHlvdSBtYWtlIHN1cmUgdGhhdCB5b3UgY29sbGVjdGVkIGluZm9ybWF0aW9uIHlvdSBpbnRlbmRlZCB0byBjb2xsZWN0Lg0KDQpBZnRlciB0ZXN0aW5nIHlvdXIgcXVlc3Rpb25uYWlyZSB5b3Ugc2hvdWxkIGJlIGFibGUgdG8gZGV0ZXJtaW5lIHdoZXRoZXI6DQoNCiogVGhlIHF1ZXN0aW9ucyBhcmUgcHJvcGVybHkgZnJhbWVkICANCiogVGhlIHF1ZXN0aW9ucyB3b3JkaW5nIHRyaWdnZXJzIGFueSBiaWFzZXMgIA0KKiBUaGUgcXVlc3Rpb25zIGFyZSBwbGFjZWQgaW4gdGhlIG9wdGltYWwgb3JkZXIgIA0KKiBUaGUgcXVlc3Rpb25zIGFyZSB1bmRlcnN0YW5kYWJsZSAgDQoqIFNwZWNpZnlpbmcgcXVlc3Rpb25zIGFyZSBuZWVkZWQgb3Igc29tZSBuZWVkIHRvIGJlIGVsaW1pbmF0ZWQgIA0KDQoNCiMjIFF1ZXN0aW9ubmFpcmUgaW4gUXVhbHRyaWNzDQoNCkEgcXVlc3Rpb25uYWlyZSBjcmVhdGlvbiBpbiBRdWFsdHJpY3Mgc3RhcnRzIHdpdGggY3JlYXRpb24gb2YgYSBRdWxhdHJpY3MgcHJvamVjdC4gRWFjaCBwcm9qZWN0IGNvbnNpc3RzIG9mIGEgc3VydmV5LCBkaXN0cmlidXRpb24gcmVjb3JkLCBhbmQgY29sbGVjdGlvbiBvZiByZXNwb25zZXMgYW5kIHJlcG9ydHMuIFRoZXJlIGFyZSB0aHJlZSB3YXlzIHRvIGNyZWF0ZSBhIHF1ZXN0aW9ubmFpcmUuRmlyc3QsIHlvdSBjYW4gY3JlYXRlIGEgbmV3IHN1cnZleSBwcm9qZWN0IGZyb20gc2NyYXRjaC4gU2Vjb25kLCB5b3UgY2FuIGNyZWF0ZSBhIG5ldyBxdWVzdGlvbm5haXJlIGZyb20gYSBjb3B5IG9mIGFuIGV4aXN0aW5nIHF1ZXN0aW9ubmFpcmUuIEV2ZW50dWFsbHksIHlvdSBjYW4gY3JlYXRlIGZyb20gYSB0ZW1wbGF0ZSBpbiB5b3VyIFN1cnZleSBMaWJyYXJ5LCBvciBmcm9tIGFuIGV4cG9ydGVkIFFTRiBmaWxlLg0KDQoNCkluIG9yZGVyIHRvIGNyZWF0ZSBhIGNvbXBsZXRlbHkgbmV3IHF1ZXN0aW9ubmFpcmUsIHlvdSBuZWVkIHRvIGRvIHRoZSBmb2xsb3dpbmc6ICANCg0KR28gdG8gdGhlIFByb2plY3RzIHBhZ2UgYnkgY2xpY2tpbmcgdGhlIFF1YWx0cmljIFhNIGxvZ28gb3IgY2xpY2tpbmcgUHJvamVjdHMgb24gdGhlIHRvcC1yaWdodC4gIA0KDQpgYGB7ciwgZWNobz1GLCBmaWcuYWxpZ249J2NlbnRlcicsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ2NyZWF0ZS1uZXctcHJvamVjdC5wbmcnKQ0KYGBgDQoNCkNyZWF0ZSBuZXcgcHJvamVjdCBieSBjbGlja2luZyB0aGUgYmx1ZSBidXR0b24gb24gdGhlIHJpZ2h0IHNpZGUuICANCkluIHRoZSAiQ3JlYXRlIHlvdXIgb3duIiBzZWN0aW9uIGNsaWNrIG9uIHRoZSBzdXJ2ZXkgYnV0dG9uLg0KDQpgYGB7ciwgZWNobz1GLCBmaWcuYWxpZ249J2NlbnRlcicsb3V0LndpZHRoPSc3MiUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ2NyZWF0ZS1uZXctcHJvamVjdC0yLnBuZycpDQpgYGANCg0KRW50ZXIgYSBuYW1lIGZvciB5b3VyIHN1cnZleSBhbmQgZ2V0IHN0YXJ0ZWQgd2l0aCBhIHN1cnZleSBjcmVhdGlvbi4NCg0KYGBge3IsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLG91dC53aWR0aD0nNzIlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCduZXctc3VydmV5LnBuZycpDQpgYGANCg0KSWYgeW91IHdvdWxkIGxpa2UgdG8gY3JlYXRlIGEgbmV3IHF1ZXN0aW9ubmFpcmUgb24gYSBiYXNpcyBvZiBhbiBhbHJlYWR5IGV4aXN0aW5nIG9uZSwgdGhlbiB5b3UgY2hvb3NlICJGcm9tIGEgQ29weSIuIFN1YnNlcWV1bnRseSwgeW91IG5lZWQgdG8gaW5kaWNhdGUgdGhlIHF1ZXN0aW9ubmFpcmUgeW91IHdvdWxkIGxpa2UgdG8gY29weS4gTm93IHlvdSBhcmUgZ29vZCB0byBnbyEgDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzcyJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnc3VydmV5LWNvcHkucG5nJykNCmBgYA0KDQpJZiB0aGVyZSBpcyBhIHF1ZXN0aW9ubmFpcmUgaW4gdGhlIFF1YWx0cmljcyBMaWJyYXJ5IHlvdSB3b3VsZCBsaWtlIHRvIHVzZSwgdGhlbiB5b3UgbmVlZCB0byBjaG9vc2UgIkZyb20gTGlicmFyeSIsIGFuZCBpbmRpY2F0ZSBvbmUgbGlicmFyeSBuYW1lIGluIHRoZSBkcm9wZG93biBtZW51LiANCg0KYGBge3IsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLG91dC53aWR0aD0nNzIlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCdsaWJyYXJ5LXN1cnZleS5wbmcnKQ0KYGBgDQoNCg0KDQojIyBRdWVzdGlvbiB0eXBlcyBhbmQgZGF0YSBhbmFseXNpcw0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCByZXN1bHRzPSdhc2lzJywgd2FybmluZz1GQUxTRSAsZXJyb3I9RkFMU0V9DQojIExvYWQgaW4gcXVhbHRSaWNzIHBhY2thZ2UNCmxpYnJhcnkocXVhbHRSaWNzKQ0KbGlicmFyeShqYW5pdG9yKQ0KbGlicmFyeShzamxhYmVsbGVkKQ0KDQojIFJlYWQgdGhlIHF1YWx0cmljcyBzdXJ2ZXkgZGF0YQ0KcXVhbHRyaWNzPC1yZWFkX3N1cnZleSgnbmV3X3F1YWx0cmljc19yZXNwb25zZV9kYXRhX2ZpbmFsX2ZpbmFsLmNzdicpDQpoZWFkKHF1YWx0cmljcykNCmRpbShxdWFsdHJpY3MpDQojVmlldyhxdWFsdHJpY3MpDQpxdWFsdHJpY3MkUTIzX0dlbmRlcg0KcXVhbHRyaWNzJFE3X01DX3NhX2NvdW50cnkNCiMgVXNpbmcgbGFiZWxzIGFzIGNvbHVtbiBuYW1lDQpvbGQuY29sbmFtZXMgPC1jb2xuYW1lcyhxdWFsdHJpY3MpDQpuZXcuY29sbmFtZXMgPC1jb2xuYW1lcyhsYWJlbF90b19jb2xuYW1lcyhxdWFsdHJpY3MpKQ0KbmV3LmNvbG5hbWVzIDwtIG1ha2UudW5pcXVlKG5ldy5jb2xuYW1lcywgc2VwPSJfIikNCmNvbG5hbWVzKHF1YWx0cmljcyk8LSBuZXcuY29sbmFtZXMNCg0KYGBgDQoNCkluIHRoaXMgY2hhcHRlciB3ZSB3aWxsIGVuY291bnRlciB0aGUgbmF0dXJlIG9mIGRhdGEgeW91IGNvbGxlY3Qgd2hlbiBjb25kdWN0aW5nIGEgc3VydmV5LiBJdCB3aWxsIGhlbHAgeW91IGNob29zZSBhIHR5cGUgb2YgYSBxdWVzdGlvbiBkZXBlbmRpbmcgb24gdGhlIG5hdHVyZSBvZiBkYXRhIHlvdSB3YW50IHRvIGNvbGxlY3QgYW5kIG9uIHRoZSB0eXBlIG9mIHN0YXRpc3RpY2FsIHRlc3RzIHlvdSB3YW50IHRvIGFwcGx5Lg0KDQpbSGVyZSB5b3UgY2FuIGZpbmQgYW4gZXhhbXBsZSBvZiBhIHF1ZXN0aW9ubmFpcmUgaW4gUXVhbHRyaWNzIHdpdGggZ3VpZGVsaW5lcyBhbmQgc3VnZ2VzdGlvbnMgcmVsYXRlZCB0byBlYWNoIHF1ZXN0aW9uIHR5cGUuXSguL0V4YW1wbGVRdWVzdGlvbm5haXJlUXVhbHRyaWNzLnFzZikNCg0KIyMjIE11bHRpcGxlIGNob2ljZSB3aXRoIGEgc2luZ2xlIGFuc3dlcg0KDQpNdWx0aXBsZSBDaG9pY2Ugd2l0aCBhIHNpbmdsZSBhbnN3ZXIgaXMgYSB0eXBlIG9mIGNsb3NlZC1lbmRlZCBxdWVzdGlvbiB0aGF0IGxldHMgcmVzcG9uZGVudHMgc2VsZWN0ICoqb25lIGFuc3dlcioqIGZyb20gYSBkZWZpbmVkIGxpc3Qgb2YgY2hvaWNlcy4NCg0KYGBge3IsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLG91dC53aWR0aD0nNzIlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCdzdXBwb3J0LW11bHRpcGxlLWNob2ljZS1xdWVzdGlvbi5wbmcnKQ0KYGBgDQoNClR5cGUgb2YgZGF0YSB5b3Ugb2J0YWluIGlzICoqY2F0ZWdvcmljYWwqKiwgYW5kIHRoZSBvdXRwdXQgY29tZXMgaW4gdGhlIGZvbGxvd2luZyBmb3JtOiAgDQpgYGB7ciwgZWNobz1GQUxTRSx3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInfQ0Ka25pdHI6OmthYmxlKHF1YWx0cmljc1sxOjYsYygiSW4gYSB0eXBpY2FsIHdlZWssIGhvdyBtYW55IGhvdXJzIGRvIHlvdSBzcGVuZCB3YXRjaGluZyBtb3ZpZXMgb3IgVFYgc2VyaWVzIG9uIE5ldGZsaXg/IildLCBjYXB0aW9uID0gIk11bHRpcGxlIENob2ljZSBRdWVzdGlvbiB3aXRoIFNpbmdsZSBBbnN3ZXIiKQ0KYGBgDQoNCiMjIyMgRGF0YSBoYW5kbGluZw0KDQpXaGF0IHRvIGRvIHdpdGggdGhpcyBkYXRhIG5vdz8gRmlyc3QsIHdlIG5lZWQgdG8gbG9hZCBpdCBpbiBSIGFuZCBwcmVwYXJlIGZvciBhbmFseXNpcy4gVGhlIG51bWJlcnMgeW91IHNlZSBpbiB0aGUgb3V0cHV0IFIgcmVjb2duaXplcyAqKmFzIG51bWVyaWMqKi4gSW4gb3JkZXIgdG8gY29uZHVjdCBzdGF0aXN0aWNhbCBtb2RlbGxpbmcgYW5kIHByb3Blcmx5IHZpc3VhbGl6ZSBvdXIgcmVzdWx0cywgd2UgbmVlZCB0byBjb252ZXJ0IG91ciBkYXRhIHRvICoqYSBmYWN0b3IgY2xhc3MuKiogICANCg0KQSBmYWN0b3IgKG9yIGNvZGluZyB2YXJpYWJsZSkgcmVwcmVzZW50cyBkaWZmZXJlbnQgZ3JvdXBzIG9mIGRhdGEgYnkgdXNpbmcgbnVtYmVycyAoaW50ZWdlcnMpLiBJbiBmYWN0LCBmYWN0b3JzIGFwcGVhciBhcyBudW1lcmljIHZhcmlhYmxlcywgYnV0IHRoZXkgaG9sZCBtZWFuaW5nIG9mIGxhYmVscy9uYW1lcyBvZiBkYXRhIGdyb3VwcywgaS5lLiBub21pbmFsIHZhcmlhYmxlLiBUaGVzZSBkYXRhIGdyb3VwcyBhcmUgcmVwcmVzZW50ZWQgaW4gYSBmb3JtIG9mICdsZXZlbHMnLiAgDQpJbiBvdXIgY2FzZSwgb3VyIG11bHRpcGxlIGNob2ljZSBxdWVzdGlvbiBvdXRwdXQgd2lsbCBjb250YWluIDQgZGF0YSBncm91cHMgKCdHcm9jZXJ5IFN0b3JlJywgJ09ubGluZSBzaG9wJywgJ1NwZWNpYWxpc2VkIGNvZmZlZSBzaG9wJywgJ290aGVyJykgYWZ0ZXIgY29udmVydGluZyBpdCB0byBmYWN0b3I6DQoNCmBgYHtyLCBldmFsPVRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQojIENvbnZlcnQgbnVtZXJpYyB2YWx1ZSB0byBmYWN0b3JzDQpxdWFsdHJpY3MkJ0luIGEgdHlwaWNhbCB3ZWVrLCBob3cgbWFueSBob3VycyBkbyB5b3Ugc3BlbmQgd2F0Y2hpbmcgbW92aWVzIG9yIFRWIHNlcmllcyBvbiBOZXRmbGl4PycgPC0gZmFjdG9yKHF1YWx0cmljcyQnSW4gYSB0eXBpY2FsIHdlZWssIGhvdyBtYW55IGhvdXJzIGRvIHlvdSBzcGVuZCB3YXRjaGluZyBtb3ZpZXMgb3IgVFYgc2VyaWVzIG9uIE5ldGZsaXg/JywgbGV2ZWxzID0gYygxOjUpLCBsYWJlbHMgPSBjKCdOZXZlcicsJzEtMiBob3VycycsJzMtNCBob3VycycsJzUtNiBob3VycycsJ21vcmUgdGhhbiA2IGhvdXJzJykpDQoNCnF1YWx0cmljcyRgIFNlbGVjdGVkIENob2ljZV8xYCA8LSBmYWN0b3IocXVhbHRyaWNzJGAgU2VsZWN0ZWQgQ2hvaWNlXzFgLGxldmVscyA9IGMoMToyKSxsYWJlbHMgPSBjKCJNYWxlIiwiRmVtYWxlIikpDQoNCnF1YWx0cmljcyRgIFNlbGVjdGVkIENob2ljZWAgPC0gZmFjdG9yKHF1YWx0cmljcyRgIFNlbGVjdGVkIENob2ljZWAsIGxldmVscyA9IGMoMToyKSwgbGFiZWxzPWMoIkF1c3RyaWEiLCJHZXJtYW55IikpDQoNCg0KIyBUYWJsZQ0KdGFibGUocXVhbHRyaWNzJCdJbiBhIHR5cGljYWwgd2VlaywgaG93IG1hbnkgaG91cnMgZG8geW91IHNwZW5kIHdhdGNoaW5nIG1vdmllcyBvciBUViBzZXJpZXMgb24gTmV0ZmxpeD8nKQ0KdGFibGUocXVhbHRyaWNzJGAgU2VsZWN0ZWQgQ2hvaWNlYCkgICAgICNjb3VudHJpZXMNCnRhYmxlKHF1YWx0cmljcyRgIFNlbGVjdGVkIENob2ljZV8xYCkgICAjZ2VuZGVyDQoNCmBgYA0KDQojIyMjIFZpc3VhbGlzYXRpb24NCg0KU2Vjb25kLCB5b3UgbWlnaHQgd2FudCB0byB2aXN1YWxpemUgeW91ciByZXN1bHRzLiBJbiBvcmRlciB0byBkbyBzbywgdGhlIGRhdGEgZm9ybWF0IG5lZWRzIHRvIGJlIGluIHRoZSBhcHByb3ByaWF0ZSBmb3JtYXQuSGVyZSB3ZSBwcm9jZWVkIHdpdGggZGF0YSBmcm9tYXQgYWRhcHRhdGlvbiBmcm9tIHRoZSBwb2ludCB3aGVyZSB3ZSBzdG9wcGVkOg0KDQpgYGB7ciwgZXZhbD1UUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KIyBDb252ZXJ0aW5nIGxvbmcgZm9ybWF0IHRvIHRoZSB2aXN1YWxpc2F0aW9uLWZyaWVuZGx5IGZvcm1hdA0KbWxjX3Zpc3VhbGlzYXRpb24gPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShxdWFsdHJpY3MkJ0luIGEgdHlwaWNhbCB3ZWVrLCBob3cgbWFueSBob3VycyBkbyB5b3Ugc3BlbmQgd2F0Y2hpbmcgbW92aWVzIG9yIFRWIHNlcmllcyBvbiBOZXRmbGl4PycpKQ0KDQojIE5hbWluZyBjb2x1bW5zDQpuYW1lcyhtbGNfdmlzdWFsaXNhdGlvbikgPC0gYygnVGltZScsJ0NvdW50JykNCg0KIyBPYnNlcnZpbmcNCm1sY192aXN1YWxpc2F0aW9uDQoNCmBgYA0KDQpUaGUgc2ltcGxpZXN0IHdheSB0byB2aXN1YWxpemUgZGF0YSBvYnRhaW5lZCBmcm9tIG11bHRpcGxlIGNob2ljZSBxdWVzdGlvbiB3aXRoIGEgc2luZ2xlIGFuc3dlciBpcyAqKmEgYmFyIGNoYXJ0Kio6DQpgYGB7cn0NCiMjIEJhc2ljIGJhciBjaGFydA0KbGFiZWxzIDwtIGFzLmNoYXJhY3RlcihtbGNfdmlzdWFsaXNhdGlvbiRUaW1lKSAjU2F2ZSBsYWJlbHMgZm9yIHgtYXhpcyBpbiB0aGUgYmFycGxvdA0KYmFycGxvdChtbGNfdmlzdWFsaXNhdGlvbiRDb3VudCwgIyBDb2x1bW4gdG8gdmlzdWFsaXplDQogICAgICAgIHhsYWI9J1RpbWUnLCAjIFgtYXhpcyBsYWJlbA0KICAgICAgICB5bGFiID0gJ0NvdW50KGFuc3dlcnMpJywgIyBZLWF4aXMgbGFiZWwNCiAgICAgICAgbmFtZXMuYXJnID0gbGFiZWxzLA0KICAgICAgICBtYWluID0gJ0hvdyBtYW55IGhvdXJzIGRvIHlvdSBzcGVuZCB3YXRjaGluZyBtb3ZpZXMgb3Igc2VyaWVzIG9uIE5ldGZsaXg/JykgIyBUaXRsZQ0KYGBgDQoNClIgcGFja2FnZSAqKmdncGxvdDIqKiBhbGxvd3MgeW91IHRvIGNyZWF0ZSB2aXN1YWxseSBhcHBlYWxpbmcgZ3JhcGhzOg0KDQpgYGB7cn0NCiMjIGdncGxvdDIgYmFyIGNoYXJ0DQpsaWJyYXJ5KGdncGxvdDIpDQpwIDwtIGdncGxvdChkYXRhPW1sY192aXN1YWxpc2F0aW9uLCANCiAgICAgICAgICAgICBhZXMoeD1UaW1lLCB5PUNvdW50LCBmaWxsPVRpbWUpKSArDQogICAgICAgICAgICAgZ2VvbV9iYXIoc3RhdD0naWRlbnRpdHknKSArIHRoZW1lX21pbmltYWwoKSArIGxhYnModGl0bGUgPSAiSW4gYSB0eXBpY2FsIHdlZWssIGhvdyBtYW55IGhvdXJzIGRvIHlvdSBzcGVuZCB3YXRjaGluZyBtb3ZpZXMgb3Igc2VyaWVzIG9uIE5ldGZsaXg/IikNCnANCmBgYA0KDQpBbm90aGVyIFIgbGlicmFyeSB3aGljaCBjYW4gaGVscCB5b3UgbWFrZSBhbWF6aW5nIGludGVyYWN0aXZlIGNoYXJ0cyBpbiBhIG1pbnV0ZSBpcyAqKnBsb3RseSoqLiBIZXJlIHdlIHVzZSBhIGZ1bmN0aW9uIGNhbGxlZCAqKmdncGxvdGx5KCkqKiwgd2hpY2ggYWxsb3dzIHlvdSB0byB0dXJuIGFueSAqKmdncGxvdDIqKiBjaGFydCBpbnRlcmFjdGl2ZS4gU2luY2Ugd2UgaGF2ZSBhbHJlYWR5IGNyZWF0ZWQgYSBiYXIgY2hhcnQgdXNpbmcgZ2dwbG90MiBhbmQgc2F2ZWQgaXQgYXMgInAiLCB3ZSB3aWxsIGp1c3QgdHVybiBpdCBpbnRvIHBsb3RseSBncmFwaDoNCg0KYGBge3Isd2FybmluZz1GLG1lc3NhZ2U9Rn0NCiMjIGdncGxvdGx5IGJhciBjaGFydA0KDQpsaWJyYXJ5KHBsb3RseSkNCmdncGxvdGx5KHApDQpgYGANCg0KDQpBbiBpbXByb3ZlZCB2ZXJzaW9uIG9mIGdncGxvdDIgcGFja2FnZSBpcyB0aGUgcGFja2FnZWQgY2FsbGVkICoqZ2d2aXMqKiwgd2hpY2ggaXMgc3RpbGwgaW4gZGV2ZWxvcGluZzoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KIyMgZ2d2aXMgYmFyIGNoYXJ0DQoNCmxpYnJhcnkoZ2d2aXMpDQpnZ3ZpcyhtbGNfdmlzdWFsaXNhdGlvbiwgDQogICAgICB4ID0gflRpbWUsIA0KICAgICAgeSA9IH5Db3VudCwgDQogICAgICBmaWxsPX5UaW1lKQ0KYGBgDQoNCiMjIyMgU3RhdGlzdGljYWwgYW5hbHlzaXMNCg0KRGF0YSB0eXBlIGNvbGxlY3RlZCBmcm9tIHRoZSBwcmV2aW91cyBxdWVzdGlvbiBpcyBvcmRpbmFsIGFzIHdlIGFyZSBhYmxlIHRvIG1ha2UgYSBuYXR1cmFsIG9yZGVyIG9mIHRoZSBsZXZlbHMuIFNpbmNlIGl0IGlzIG9yZGluYWwgZGF0YSB0eXBlLCBpdCBiZWxvbmdzIHRvIGNhdGVnb3JpY2FsIGRhdGEuIEZvciB0aGUgYW5hbHlzaXMgb2YgY2F0ZWdvcmljYWwgZGF0YSB3ZSBjYW4gdXNlIENoaS1zcXVhcmUgdGVzdCBvciBGaXNoZXIncyB0ZXN0IGlmIGEgY291bnQgZm9yIHNvbWUgbGV2ZWwgaXMgbGVzcyB0aGFuIDUuIA0KDQojIyMjIyBGaXNjaGVyJ3MgZXhhY3QNCg0KRmlzaGVyJ3MgZXhhY3QgdGVzdCBpcyB1c2VkIHRvIHRlc3QgYSBoeXBvdGhlc2lzIHdpdGggZGF0YSBvYnRhaW5lZCBmcm9tIG11bHRpcGxlIGNob2ljZSBxdWVzdGlvbnMgd2l0aCBzaW5nbGUgYW5zd2VyLiBSZXN1bHRzIGZyb20gbXVsdGlwbGUgY2hvaWNlIHF1ZXN0aW9ucyB3aXRoIG11bHRpcGxlIGFuc3dlcnMgYXJlIHRyZWF0ZWQgd2l0aCBkaWZmZXJlbnQgdGVzdC4NCjx1bD48bGk+IDxCPiBBcHBsaWNhdGlvbjogPC9CPiB3aGVuIHlvdSBoYXZlIDxCPiAxIGRlcGVuZGVudCB2YXJpYWJsZSBhbmQgIDEgaW5kZXBlbmRlbnQgdmFyaWFibGUgd2l0aCAyIG9yIG1vcmUgbGV2ZWxzL2ZhY3RvcnMgPC9CPjwvdWw+PC9saT4NCjx1bD48bGk+IFVzZWQgd2hlbiBmcmVxdWVuY3kgaW4gYXQgbGVhc3Qgb25lIGNlbGwgaXMgPEI+IGxlc3MgdGhhbiA1IDwvQj4uIFdoZW4gZnJlcXVlbmNpZXMgaW4gZWFjaCBjZWxsIGFyZSBncmVhdGVyIHRoYW4gNSwgQ2hpLXNxdWFyZSB0ZXN0IHNob3VsZCBiZSB1c2VkLjwvdWw+PC9saT4NCjx1bD48bGk+IDxCPkh5cG90aGVzaXM6PC9CPiBJcyB0aGVyZSBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gZnJlcXVlbmNpZXMgYmV0d2VlbiB2YWx1ZXMgb2JzZXJ2ZWQgaW4gY2VsbHMgYW5kIHZhbHVlcyBleHBlY3RlZCBpbiBjZWxscyA/IChSIGZvciBNYXJrZXRpbmcgYW5kIFJlc2VhcmNoIEFuYWx5dGljcyk8L3VsPjwvbGk+DQo8dWw+PGxpPiA8Qj5IMDo8L0I+IFRoZXJlIGlzIG5vIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB0d28gY2F0ZWdvcmljYWwgdmFyaWFibGVzLlRoZXJlZm9yZSwgdHdvIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBhcmUgPEI+IGluZGVwZW5kZW50LjwvQj4gS25vd2luZyB0aGUgdmFsdWUgb2Ygb25lIHZhcmlhYmxlIGRvZXMgbm90IGhlbHAgdG8gcHJlZGljdCB0aGUgdmFsdWUgb2YgdGhlIG90aGVyIHZhcmlhYmxlLjwvdWw+PC9saT4NCjx1bD48bGk+IDxCPkgxOjwvQj4gVGhlcmUgaXMgYSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdHdvIGNhdGVnb3JpY2FsIHZhcmlhYmxlcy5UaGVyZWZvcmUsIHR3byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYXJlIDxCPiBkZXBlbmRlbnQuPC9CPktub3dpbmcgdGhlIHZhbHVlIG9mIG9uZSB2YXJpYWJsZSBoZWxwcyB0byBwcmVkaWN0IHRoZSB2YWx1ZSBvZiB0aGUgb3RoZXIgdmFyaWFibGUuPC91bD48L2xpPg0KPHVsPjxsaT4gVXN1YWxseSwgdGhpcyB0eXBlIG9mIHRlc3QgaXMgdXNlZCBvbiAyeDIgY29udGluZ2VuY3kgdGFibGVzLiBIb3dldmVyLCBpdCBjYW4gYmUgYXBwbGljYWJsZSBvbiBjb250aW5nZW5jeSB0YWJsZXMgb2YgbGFyZ2VyIGRpbWVuc2lvbnMuPC91bD48L2xpPg0KDQo8Qj5FeGFtcGxlOjwvQj4gV2Ugd291bGQgbGlrZSB0byBrbm93IHdoZXRoZXIgYSBudW1iZXIgb2YgaG91cnMgc3BlbnQgd2F0Y2hpbmcgTmV0ZmxpeCBkZXBlbmRzIG9uIHRoZSByZXNwb25kZW50cycgY291bnRyeSBvZiBvcmlnaW4uDQoNCg0KYGBge3J9DQojIENyZWF0aW9uIG9mIGNvbnRpbmdlbmN5IHRhYmxlDQpmaXNoZXJfdGVzdF90YWJsZSA8LXRhYmxlKHF1YWx0cmljcyRgIFNlbGVjdGVkIENob2ljZWAscXVhbHRyaWNzJCdJbiBhIHR5cGljYWwgd2VlaywgaG93IG1hbnkgaG91cnMgZG8geW91IHNwZW5kIHdhdGNoaW5nIG1vdmllcyBvciBUViBzZXJpZXMgb24gTmV0ZmxpeD8nKQ0KIyBDaGVjayBob3cgb3VyIGNvbnRpZ2VuY3kgdGFibGUgbG9va3MgbGlrZQ0KZmlzaGVyX3Rlc3RfdGFibGUNCg0KIyBTaW5jZSB3ZSBoYXZlIGEgY291bnQgbGVzcyB0aGFuIDUsIHdlIHNob3VsZCBhcHBseSBGaXNoZXIncyB0ZXN0IGluc3RlYWQgb2YgQ2hpLXNxdWFyZS4NCg0KIyBGaXNoZXIncyB0ZXN0DQp0ZXN0IDwtIGZpc2hlci50ZXN0KGZpc2hlcl90ZXN0X3RhYmxlKQ0KdGVzdA0KDQojIHAtdmFsdWUNCnRlc3QkcC52YWx1ZQ0KYGBgDQoNCkZyb20gdGhlIG91dHB1dCBhbmQgZnJvbSB0ZXN0JHAudmFsdWUgd2Ugc2VlIHRoYXQgdGhlIHAtdmFsdWUgaXMgaGlnaGVyIHRoYW4gdGhlIHNpZ25pZmljYW5jZSBsZXZlbCBvZiA1JS4gTGlrZSBhbnkgb3RoZXIgc3RhdGlzdGljYWwgdGVzdCwgaWYgdGhlIHAtdmFsdWUgaXMgaGlnaGVyIHRoYW4gdGhlIHNpZ25pZmljYW5jZSBsZXZlbCwgd2UgY2FuIG5vdCByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4NCg0KSW4gb3VyIGNhc2UsIG5vdCByZWplY3RpbmcgdGhlIG51bGwgaHlwb3RoZXNpcyBmb3IgdGhlIEZpc2hlcuKAmXMgZXhhY3QgdGVzdCBvZiBpbmRlcGVuZGVuY2UgbWVhbnMgdGhhdCB0aGVyZSBpcyBubyBzaWduaWZpY2FudCByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdHdvIGNhdGVnb3JpY2FsIHZhcmlhYmxlcy4gVGhlcmVmb3JlLCBrbm93aW5nIHRoZSB2YWx1ZSBvZiBvbmUgdmFyaWFibGUgZG9lcyBub3QgaGVscCB0byBwcmVkaWN0IHRoZSB2YWx1ZSBvZiB0aGUgb3RoZXIgdmFyaWFibGUuDQoNCiMjIyMjIENoaS1zcXVhcmUgdGVzdDogR29vZG5lc3Mgb2YgZml0ICYgSW5kZXBlbmRlbmNlIHRlc3QNCg0KMSkgR29vZG5lc3Mgb2YgZml0DQo8ZGl2Pjx1bD48bGk+PEI+IEFwcGxpY2F0aW9uOiA8L0I+d2hlbiB5b3Ugb25seSBoYXZlIDxCPiAxIGRlcGVuZGVudCB2YXJpYWJsZSBhbmQgbm9uZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgPC9CPjwvdWw+PC9saT4NCjx1bD48bGk+IDxCPiBIeXBvdGhlc2lzOjwvQj4gSXMgdGhlcmUgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIGZyZXF1ZW5jaWVzIGJldHdlZW4gdmFsdWVzIG9ic2VydmVkIGluIGNlbGxzIGFuZCB2YWx1ZXMgZXhwZWN0ZWQgaW4gY2VsbHMgPyAoUiBmb3IgTWFya2V0aW5nIGFuZCBSZXNlYXJjaCBBbmFseXRpY3MpIDwvdWw+PC9saT4NCjx1bD48bGk+IDxCPiBIMDogPC9CPiBUaGVyZSBpcyBubyBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG9ic2VydmVkIGFuZCB0aGUgZXhwZWN0ZWQgZnJlcXVlbmNpZXMuPC91bD48L2xpPg0KPHVsPjxsaT4gPEI+IEgxOiA8L0I+IFRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBvYnNlcnZlZCBhbmQgdGhlIGV4cGVjdGVkIGZyZXF1ZW5jaWVzLiA8L3VsPjwvbGk+DQo8dWw+PGxpPiBJZiB3ZSBkb24ndCBzcGVjaWZ5IGV4cGVjdGVkIGZyZXF1ZW5jeSBwZXIgY2VsbCAoc2VlIGluIHRoZSBjb2RlIGJlbG93KSwgdGhlbiBpdCBpcyBleHBlY3RlZCB0aGF0IGFsbCBjZWxscyBzaG93IGFuIGVxYXVsIGZyZXF1ZW5jeS4gPC91bD48L2xpPg0KPHVsPjxsaT4gPEI+IEV4YW1wbGU8L0I+IDonRG8gdGhlIG51bWJlcnMgb2YgcmVzcG9uZGVudHMgd2hvIGFyZSBzcGVuZGluZyBkaWZmZXJlbnQgYW1vdW50IG9mIGhvdXJzIHdhdGNoaW5nIE5ldGZsaXggPEI+IHNpZ25pZmljYW50bHkgZGlmZmVyIGZyb20gZWFjaCBvdGhlcj88L0I+JzwvdWw+PC9saT48L2Rpdj4NCjx1bD48bGk+PEI+IE5vdGUgdGhhdCB3ZSBkaWQgbm90IGFzc3VtZSBhbnkgc3BlY2lmaWMgZGlzdHJpYnV0aW9uLCBzbyB3ZSBhcmUgYXNzdW1pbmcgdGhhdCBlYWNoIGNvdW50IHdpbGwgaGF2ZSB0aGUgc2FtZSBvciBzaW1pbGFyIG51bWJlci4gPHVsPjxsaT48L0I+DQoNCmBgYHtyfSANCiMgQ3JlYXRpbmcgdGFibGUgDQoobWxjX2NoaV9zcXVhcmUgPC0gdGFibGUocXVhbHRyaWNzJCdJbiBhIHR5cGljYWwgd2VlaywgaG93IG1hbnkgaG91cnMgZG8geW91IHNwZW5kIHdhdGNoaW5nIG1vdmllcyBvciBUViBzZXJpZXMgb24gTmV0ZmxpeD8nKSkNCiAgICAgIA0KIyBDaGktc3F1YXJlIHRlc3QgKHdpdGhvdXQgZ2l2ZW4gZXhwZWN0ZWQgdmFsdWVzID0gZXF1YWwgdmFsdWVzICkNCmNoaXNxLnRlc3QobWxjX2NoaV9zcXVhcmUpDQpgYGANCg0KVGhlIHAtdmFsdWUgb2YgdGhlIHRlc3QgaXMgaGlnaGVyIHRoYW4gMC4wNS4gV2UgY2FuIGNvbmNsdWRlIHRoYXQgdGhlIG51bWJlcnMgb2YgcmVzcG9uZGVudHMgd2hvIHNwZW50IGRpZmZlcmVudCBhbW91bnQgb2YgaG91cnMgd2F0Y2hpbmcgTmV0ZmxpeCBhcmUgY29tbW9ubHkgZGlzdHJpYnV0ZWQuIE9ic2VydmVkIGRpc3RyaWJ1dGlvbiBkb2VzIG5vdCBkaWZmZXIgc2lnbmlmaWNhbnRseSBmcm9tIHRoZSBleHBlY3RlZC4gVGhpcyByZXN1bHQgZG9lcyBub3Qgc3VycHJpc2UgaWYgeW91IHRha2UgYSBsb29rIGF0IHRoZSB2YWx1ZXMgZm9yIGVhY2ggbGV2ZWwgaW4gdGhlIHRhYmxlIHdlIGNyZWF0ZWQgYmVmb3JlIGNvbmR1Y3RpbmcgdGhlIHRlc3QuIFRoZXJlIHlvdSBjYW4gc2VlIHRoYXQgY291bnQgb2YgYW5zd2VycyBpbiBlYWNoIGxldmVsIGlzIG1vcmUgb3IgbGVzcyBub3QgZGV2aWF0aW5nIHRvbyBtdWNoLiBJdCBpcyB2aXNpYmxlIGlmIHlvdSB0YWtlIGEgbG9vayBhdCB0aGUgcHJldmlvdXMgdmlzdWFsaXNhdGlvbnMgYXMgd2VsbC4NCg0KDQpJZiB3ZSBhcmUgaW50ZXJlc3RlZCBpbiB0ZXN0aW5nIG1vcmUgc3BlY2lmaWMgZGlzdHJpYnV0aW9uLCBpLmUuIGV4cGVjdCB0aGF0IDQwJSBvZiBvdXIgcmVzcG9uZGVudHMgYXJlIHdhdGNoaW5nIE5ldGZsaXggMy00IGhvdXJzLCB3ZSBjYW4gaW50cm9kdWNlIGNvcnJlc3BvbmRpbmcgZGlzdHJpYnV0aW9uIGluIHRoZSB0ZXN0LiANCg0KYGBge3J9DQojIEV4cGVjdGVkIHZhbHVlcyBpbiBwZXJjZW50YWdlcyBmb3IgZWFjaCBhbHRlcm5hdGl2ZS4gVGhlIHN1bSBtdXN0IGJlIDEuDQpleHBlY3RlZF92YWx1ZXMgPC0gYygwLjEwLCAjIFdlIGV4cGVjdCB0aGF0IDEwJSBvZiBvdXIgcmVzcG9uZGVudHMgZG8gbm90IHdhdGNoIE5ldGZsaXggYXQgYWxsICgiTmV2ZXIiKS4NCiAgICAgICAgICAgICAgICAgICAgIDAuMjAsICMgV2UgZXhwZWN0IHRoYXQgMjAlIG9mIG91ciByZXNwb25kZW50cyB3YXRjaCBOZXRmbGl4IDEtMiBob3VycyBhIHdlZWsuICANCiAgICAgICAgICAgICAgICAgICAgIDAuNDAsICMgV2UgZXhwZWN0IHRoYXQgNDAlIG9mIG91ciByZXNwb25kZW50cyB3YXRjaCBOZXRmbGl4IDMtNCBob3VycyBhIHdlZWsuDQogICAgICAgICAgICAgICAgICAgICAwLjIwLCAjIFdlIGV4cGVjdCB0aGF0IDIwJSBvZiBvdXIgcmVzcG9uZGVudHMgd2F0Y2ggTmV0ZmxpeCA1LTYgaG91cnMgYSB3ZWVrLg0KICAgICAgICAgICAgICAgICAgICAgMC4xMCAjIFdlIGV4cGVjdCB0aGF0IDEwJSBvZiBvdXIgcmVzcG9uZGVudHMgd2F0Y2ggTmV0ZmxpeCBtb3JlIHRoYW4gNiBob3VycyBhIHdlZWsuDQogICAgICAgICAgICAgICAgICAgICkNCiMgQ2hpLXNxdWFyZSB0ZXN0IHdpdGggZXhwZWN0ZWQgdmFsdWVzDQpjaGlzcS50ZXN0KG1sY19jaGlfc3F1YXJlLCBwPWV4cGVjdGVkX3ZhbHVlcykNCmBgYA0KDQpUaGlzIHRpbWUgdGhlIHAtdmFsdWUgb2YgdGhlIHRlc3QgaXMgbG93ZXIgdGhhbiAwLjA1LldlIGhhdmUgYW4gZXZpZGFuY2UgdGhhdCBvYnNlcnZlZCBkaXN0cmlidXRpb24gZG9lcyBzaWduaWZpY2FudGx5IGRpZmZlciBmcm9tIHRoZSBleHBlY3RlZCBkaXN0cmlidXRpb24gKDEwJS8yMCUvNDAlLzIwJS8xMCUpLg0KDQoyKSBDaGktU3F1YXJlIFRlc3Qgb2YgSW5kZXBlbmRlbmNlDQo8ZGl2Pjx1bD48bGk+IDxCPiBBcHBsaWNhdGlvbjogPC9CPndoZW4geW91IGhhdmUgPEI+IDEgZGVwZW5kZW50IHZhcmlhYmxlIGFuZCAgMSBpbmRlcGVuZGVudCB2YXJpYWJsZSB3aXRoIDIgb3IgbW9yZSBsZXZlbHMvZmFjdG9ycyA8L0I+PC91bD48L2xpPiANCjx1bD48bGk+IDxCPiBIeXBvdGhlc2lzOiA8L0I+IElzIHRoZXJlIGFuIGFzc29jaWF0aW9uIGJldHdlZW4gY2F0ZWdvcmljYWwgdmFyaWFibGUgWCBhbmQgY2F0ZWdvcmljYWwgdmFyaWFibGUgWT8gPC91bD48L2xpPg0KPHVsPjxsaT4gPEI+IEgwOiA8L0I+IFRoZXJlIGlzIG5vIGFzc29jaWF0aW9uIGJldHdlZW4gdGhlIHR3byB2YXJpYWJsZXMuPC9CPjwvdWw+PC9saT4NCjx1bD48bGk+IDxCPiBIMTogPC9CPiBUaGVyZSBpcyBhbiBhc3NvY2lhdGlvbiBiZXR3ZWVuIHRoZSB0d28gdmFyaWFibGVzLjwvQj48L3VsPjwvbGk+DQo8dWw+PGxpPiA8Qj4gRXhhbXBsZTogPC9CPiBJcyB0aGVyZSBhbiBhc3NvY2lhdGlvbiBiZXR3ZWVuIGdlbmRlciBhbmQgdGhlIGhvdXJzIHNwZW50IHdhdGNoaW5nIE5lZmxpeCBkdXJpbmcgYSB3ZWVrPyA8L3VsPjwvbGk+PC9kaXY+DQoNCmBgYHtyfQ0KIyBDcmVhdGlvbiBvZiBjb250aW5nZW5jeSB0YWJsZQ0KY2hpX3NxdWFyZV90YWJsZSA8LXRhYmxlKHF1YWx0cmljcyRgIFNlbGVjdGVkIENob2ljZV8xYCxxdWFsdHJpY3MkJ0luIGEgdHlwaWNhbCB3ZWVrLCBob3cgbWFueSBob3VycyBkbyB5b3Ugc3BlbmQgd2F0Y2hpbmcgbW92aWVzIG9yIFRWIHNlcmllcyBvbiBOZXRmbGl4PycpDQoNCiMgQ2hpLXNxdWFyZSBpbmRlcGVuZGVuY2UgdGVzdA0KY2hpc3EudGVzdChjaGlfc3F1YXJlX3RhYmxlKQ0KYGBgDQoNClNpbmNlIHRoZSBwLXZhbHVlICgwLjgxMzUpIGlzIGhpZ2hlciB0aGFuIHRoZSBzaWduaWZpY2FuY2UgbGV2ZWwgKDAuMDUpLCB3ZSBjYW5ub3QgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuIFRodXMsIHdlIGNvbmNsdWRlIHRoYXQgdGhlcmUgaXMgbm8gYXNzb2NpYXRpb24gcmVsYXRpb25zaGlwIGJldHdlZW4gZ2VuZGVyIGFuZCBudW1iZXIgb2YgaG91cnMgc3BlbnQgd2F0Y2hpbmcgTmV0ZmxpeC4gVGhlcmVmb3JlLCB3ZSBjYW4gc2F5IHRoYXQgdGhlIGhvdXJzIHNwZW50IGlzIGluZGVwZW5kZW50IGZyb20gdGhlIGdlbmRlciBvZiBwYXJ0aWNpcGFudC4NCg0KIyMjIE11bHRpcGxlIGNob2ljZSB3aXRoIG11bHRpcGxlIGFuc3dlcnMNCg0KYGBge3IsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLG91dC53aWR0aD0nNzIlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCdtdWx0aXBsZS1jaG9pY2UtcXVlc3Rpb24tbXVsdGlwbGUtYW5zd2Vycy5wbmcnKQ0KYGBgDQoNCkJlZm9yZSB3ZSBjb25kdWN0IGFueSB0ZXN0LCB3ZSB3aWxsIGRvIHNvbWUgc2ltcGxlIGNhbGN1bGF0aW9zIGFuZCB2aXN1YWxpc2Ugb3VyIGRhdGEuIA0KDQpgYGB7cn0NCiMgUmVuYW1lIGNvbHVtbnMNCmNvbG5hbWVzKHF1YWx0cmljcylbMzhdIDwtICJqYSFOYXR1cmxpY2giDQpjb2xuYW1lcyhxdWFsdHJpY3MpWzM5XSA8LSAiQ2xldmVyIg0KY29sbmFtZXMocXVhbHRyaWNzKVs0MF0gPC0gIlNwYXIgVml0YWwiDQpjb2xuYW1lcyhxdWFsdHJpY3MpWzQxXSA8LSAiLi4uIg0KDQojIFJlcGxhY2luZyBOQSB3aXRoIDANCnF1YWx0cmljcyRgamEhTmF0dXJsaWNoYFtpcy5uYShxdWFsdHJpY3MkYGphIU5hdHVybGljaGApXT0wDQpxdWFsdHJpY3MkQ2xldmVyW2lzLm5hKHF1YWx0cmljcyRDbGV2ZXIpXT0wDQpxdWFsdHJpY3MkYFNwYXIgVml0YWxgW2lzLm5hKHF1YWx0cmljcyRgU3BhciBWaXRhbGApXT0wDQpxdWFsdHJpY3MkLi4uW2lzLm5hKHF1YWx0cmljcyQuLi4pXT0wDQoNCiMgQ2FsY3VsYXRpbmcgZnJlcXVlbmN5LCBwZXJjZW50YWdlIG9mIHJlc3BvbmRlbnRzIGFuZCBwZXJjZW50YWdlIG9mIGNhc2VzDQpkZi5jb2NocmFuIDwtIGRhdGEuZnJhbWUoRnJlcXVuZWN5ID0gY29sU3VtcyhxdWFsdHJpY3NbMzg6NDFdKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBTaGFyZV9vZl9yZXNwb25kZW50cyA9IChjb2xTdW1zKHF1YWx0cmljc1szODo0MV0pL3N1bShxdWFsdHJpY3NbMzg6NDFdKSkqMTAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTaGFyZV9vZl9jYXNlcyA9KChjb2xTdW1zKHF1YWx0cmljc1szODo0MV0pKS9ucm93KHF1YWx0cmljc1szODo0MV0pKSoxMDApDQojIE9ic2VydmluZw0KZGYuY29jaHJhbg0KDQojIFZpc3VhbGlzYXRpb24NCmJhcnBsb3QoZGYuY29jaHJhblssM10sIG5hbWVzLmFyZyA9IHJvdy5uYW1lcyhkZi5jb2NocmFuKSwgbWFpbiA9ICIlIG9mIFJlc3BvbmRlbnRzIGZhbWlsaWFyIHdpdGggYnJhbmRzIiwgeGxhYiA9ICJCcmFuZCIseWxhYiA9ICJQZXJjZW50YWdlIikNCmBgYA0KDQpUaGUgdmlzdWFsaXNhdGlvbiBhYm92ZSBkZXBpY3RzIHRoZSBmYWN0IHRoYXQgbW9yZSB0aGFuIDYwJSBwZXJjZW50IG9mIHBlb3BsZSBhcmUgZmFtaWxpYXIgd2l0aCB0aGUgYnJhbmQgImphIU5hdHVybGljaCIsIHdoaWxlIHdlIGNhbiBub3Qgc2F5IHRoZSBzYW1lIGZvciBvdGhlciBicmFuZHMgY29uc2lkZXJlZCBpbiBvdXIgcXVlc3Rpb24uIA0KDQoNCkZvciB0aGUgYW5hbHlzaXMgb2YgcmVzdWx0cyBjb2xsZWN0ZWQgd2l0aCBtdWx0aXBsZSBjaG9pY2UgcXVlc3Rpb24gd2l0aCBtdWx0aXBsZSBwb3NzaWJsZSBhbnN3ZXJzLCB3ZSBjYW4gdXNlICoqQ29jaHJhbidzIFEgdGVzdC4qKkFsdGhvdWdoIHdlIGRpZCBub3QgbWVudGlvbiBpdCBiZWZvcmUsIGl0IGlzIG5vdCB0b28gZGlmZmVyZW50IGZyb20gd2hhdCB5b3UgaGF2ZSBhbHJlYWR5IGxlYXJuZWQgYWJvdXQgb3RoZXIgdGVzdHMuIA0KDQpUaGUgQ29jaHJhbuKAmXMgUSB0ZXN0IGFuZCBhc3NvY2lhdGVkIG11bHRpcGxlIGNvbXBhcmlzb25zIHJlcXVpcmUgdGhlIGZvbGxvd2luZyBhc3N1bXB0aW9uczoNCjEuIFJlc3BvbnNlcyBhcmUgZGljaG90b21vdXMgYW5kIGZyb20gayBudW1iZXIgb2YgbWF0Y2hlZCBzYW1wbGVzLg0KMi4gVGhlIHN1YmplY3RzIGFyZSBpbmRlcGVuZGVudCBvZiBvbmUgYW5vdGhlciBhbmQgd2VyZSBzZWxlY3RlZCBhdCByYW5kb20gZnJvbSBhIGxhcmdlciBwb3B1bGF0aW9uLg0KMy4gVGhlIHNhbXBsZSBzaXplIGlzIHN1ZmZpY2llbnRseSDigJxsYXJnZeKAnS4gKEFzIGEgcnVsZSBvZiB0aHVtYiwgdGhlIG51bWJlciBvZiBzdWJqZWN0cyBmb3Igd2hpY2ggdGhlDQpyZXNwb25zZXMgYXJlIG5vdCBhbGwgMOKAmXMgb3IgMeKAmXMsIG4sIHNob3VsZCBiZSDiiaUgNCBhbmQgbmsgc2hvdWxkIGJlIOKJpSAyNCkNCg0KSW4gYSB3aXRoaW4tc3ViamVjdHMgZXhwZXJpbWVudCBkZXNpZ24gd2l0aCB0aHJlZSBvciBtb3JlIG9ic2VydmF0aW9ucyBvZiBhIGRpY2hvdG9tb3VzKD0ganVzdCB0d28gbGV2ZWxzIHN1Y2ggYXMgIlllcyIgb3IgIk5vIikgY2F0ZWdvcmljYWwgb3V0Y29tZSwgeW91IHV0aWxpemUgQ29jaHJhbidzIFEgdGVzdCB0byBhc3Nlc3MgbWFpbiBlZmZlY3RzLlNpbWlsYXJseSwgaW4gb3VyIG11bHRpcGxlIGNob2ljZSBxdWVzdGlvbiB3aXRoIG11bHRpcGxlIGFuc3dlcnMgd2UgaGF2ZSB0aGUgc2FtZSByZXNwb25kZW50IGdvaW5nIHRocm91Z2ggdGhyZWUgb3IgbW9yZSBwb3RlbnRpYWwgYW5zd2VycyB3aXRoIGRpY2hvdG9tb3VzKD15ZXMgb3Igbm8pIGNhdGVnb3JpY2FsIG91dGNvbWUuIA0KDQoNCmBgYHtyfQ0KbGlicmFyeShub25wYXIpDQoNCiMgQ3JlYXRpb24gb2YgbWF0cml4DQptYXRyaXguY29jaHJhbiA8LSBjYmluZChxdWFsdHJpY3MkYGphIU5hdHVybGljaGAsDQogICAgICAgICAgICAgICAgICAgcXVhbHRyaWNzJENsZXZlciwNCiAgICAgICAgICAgICAgICAgICBxdWFsdHJpY3MkYFNwYXIgVml0YWxgLA0KICAgICAgICAgICAgICAgICAgIHF1YWx0cmljcyQuLi4pDQojIFR1cm5pbmcgTkFzIHRvIDANCm1hdHJpeC5jb2NocmFuW2lzLm5hKG1hdHJpeC5jb2NocmFuKV09MA0KDQojIENvY2hyYW4gdGVzdCAgICAgICAgICAgICAgICAgICANCmNvY2hyYW5zLnEobWF0cml4LmNvY2hyYW4sIGFscGhhID0gMC4wNSkNCg0KYGBgDQoNClRoZSBwLXZhbHVlIGxlc3MgdGhhbiAwLjA1IGluZGljYXRlcyB0aGF0IHRoZXJlIGlzIGVub3VnaCBldmlkZW5jZSB0byBjb25jbHVkZSB0aGF0IHNvbWUgb2YgdGhlIHN0b3JlIGJyYW5kcyBhcmUgYmV0dGVyIGtub3duIGFtb25nIG91ciByZXNwb25kZW50cyB0aGFuIG90aGVyLiBJbiBvcmRlciB0byB0YWtlIGEgY2xvc2VyIGxvb2sgYXQgaXQsIHdlIG5lZWQgdG8gY29uZHVjdCBhIHBvc3QgaG9jIHRlc3QuDQoNCmBgYHtyfQ0KbGlicmFyeShEZXNjVG9vbHMpDQpsaXN0LmNvY2hyYW4gPC0gbGlzdChxdWFsdHJpY3MkYGphIU5hdHVybGljaGAsDQogICAgICAgICAgICAgICAgICAgcXVhbHRyaWNzJENsZXZlciwNCiAgICAgICAgICAgICAgICAgICBxdWFsdHJpY3MkYFNwYXIgVml0YWxgLA0KICAgICAgICAgICAgICAgICAgIHF1YWx0cmljcyQuLi4pDQoNCiMgUmVwbGFjaW5nIE5BcyBpbiB0aGUgbGlzdCB3aXRoIDAgaW4gb3JkZXIgdG8gYmUgYWJsZSB0byBydW4gdGhlIHRlc3QNCmxpc3QuY29jaHJhbiA8LSByYXBwbHkobGlzdC5jb2NocmFuLCBmPWZ1bmN0aW9uKHgpIGlmZWxzZShpcy5uYSh4KSwwLHgpLCBob3c9InJlcGxhY2UiICkNCg0KIyBQb3N0IGhvYyB0ZXN0IChEdW5uIFRlc3QpDQpEdW5uVGVzdChsaXN0LmNvY2hyYW4sIG1ldGhvZD0iYm9uZmVycm9uaSIpDQoNCmBgYA0KDQpGcm9tIHRoZSByZXN1bHRzIG9mIHRoZSBEdW5uIFRlc3QsIHdlIGNhbiBzZWUgdGhhdCB0aGVyZSBpcyBhIGJpZyBkaWZmZXJlbmNlIGJldHdlZW4gMSAoImphIU5hdMO8cmxpY2giKSBhbmQgNCgiLi4uIiksIGFzIHdlbGwgYXMgYmV0d2VlbiA0KCIuLi4iKSBhbmQgMygiU3BhciBWaXRhbCIpLiANCg0KIyMjIFJhbmsgb3JkZXIgcXVlc3Rpb24NCg0KYGBge3IsIGVjaG89RiwgZmlnLmFsaWduPSdjZW50ZXInLG91dC53aWR0aD0nNzIlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCdyYW5rLW9yZGVyLXF1ZXN0aW9uLnBuZycpDQpgYGANCg0KQSByYW5rIG9yZGVyIHF1ZXN0aW9uIGFza3MgcmVzcG9uZGVudHMgdG8gY29tcGFyZSBpdGVtcyB0byBlYWNoIG90aGVyIGJ5IHBsYWNpbmcgdGhlbSBpbiBvcmRlciBvZiBwcmVmZXJlbmNlLiBOb3RlIHRoYXQgdGhlIGRhdGEgb2J0YWluZWQgZnJvbSBhIHJhbmsgb3JkZXIgcXVlc3Rpb24gc2hvd3MgYW4gb3JkZXIgb2YgYSByZXNwb25kZW50J3MgcGVyZWZlcmVuY2UsIGJ1dCBub3QgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBpdGVtcy4gRm9yIGluc3RhbmNlLCBpZiB0aGUgdGhlIG1vc3QgaW1wb3J0YW50IGZlYXR1cmUgb2YgYSBmaXRuZXNzIHRyYWNrZXIgZm9yIGEgcmVzcG9uZGVuZHQgWFkgaXMgIk1lYXN1cmluZyBzdGVwcyIgYW5kIHRoZSBzZWNvbmQgbW9zdCBpbXBvcnRhbnQgZmVhdHVyZSAiQ2Fsb3JpZXMgYnVybmVkIiwgd2UgZG9uJ3Qga25vdyBmb3IgaG93IG11Y2ggbW9yZSBpbXBvcnRhbnQgaXMgdGhlIGZvcm1lciBvbmUgaW4gY29tcGFyaXNvbiB0byB0aGUgbGF0dGVyIG9uZS4NCg0KSW50dWl0aXZlIHF1ZXN0aW9uIHRvIGFzayBpcyB0aGUgZm9sbG93aW5nOiB3aGljaCBmZWF0dXJlIG9mIHRoZSBmaXRuZXNzIHRyYWNrZXIgaXMgdGhlIG1vc3QgaW1wb3J0YW50IGZvciBvdXIgcmVzcG9uZGVudHM/DQoNCldlIGNhbiBhbnN3ZXIgdGhpcyBxdWVzdGlvbiBieSBjYWxjdWxhdGluZyBhIG1lYW4gcmFuayBmb3IgZWFjaCBmZWF0dXJlLiBCZWZvcmUgd2UgZG8gc28sIHdlIHdpbGwgY3JlYXRlIGEgc2VwYXJhdGUgZGF0YSBmcmFtZSBhbmQgYWRkIGNvbHVtbnMgb2YgdGhlIHJlc3BvbnNlIGRhdGEuDQpgYGB7cn0NCnJhbmsuZGF0YSA8LSBkYXRhLmZyYW1lKHF1YWx0cmljcyRgIE1lYXN1cmluZyBzdGVwc2AsDQogICAgICAgICAgICAgICAgICAgICAgICBxdWFsdHJpY3MkYCBDYWxvcmllcyBidXJuZWRgLA0KICAgICAgICAgICAgICAgICAgICAgICAgcXVhbHRyaWNzJGAgTWVhc3VyaW5nIGhlYXJ0YmVhdGAsDQogICAgICAgICAgICAgICAgICAgICAgICBxdWFsdHJpY3MkYCBFeGVyY2lzZSB0cmFja2luZ2AsDQogICAgICAgICAgICAgICAgICAgICAgICBxdWFsdHJpY3MkYCBNZWFzdXJpbmcgZGlzdGFuY2VgKQ0KY29sbmFtZXMocmFuay5kYXRhKTwtYygiTWVhc3VyaW5nIHN0ZXBzIiwiQ2Fsb3JpZXMgYnVybmVkIiwiTWVhc3VyaW5nIGhlYXJ0YmVhdCIsIkV4ZXJjaXNlIHRyYWNraW5nIiwiTWVhc3VyaW5nIGRpc3RhbmNlIikNCg0KYGBgDQoNCkZpcnN0IGluZm9ybWF0aW9uIHdlIHdvdWxkIGxpa2UgdG8ga25vdyBpcyBob3cgbWFueSBwcmVmZXJlbmNlIGNvbWJpbmF0aW9ucyB0aGVyZSBhcmUsIGFuZCBob3cgcmVwZXRpdGl2ZSB0aGV5IGFyZS4gV2UgY2FuIG9idGFpbiB0aGF0IGluZm9ybWF0aW9uIGJ5IGNyZWF0aW5nIGEgc3VtbWFyeSBvZiB0aGUgcmFua2luZyBkYXRhIGZyYW1lIHdlIGNyZWF0ZWQuIA0KYGBge3J9DQpsaWJyYXJ5KHBtcikNCnRlc3QgPC0gcmFua2FnZyhyYW5rLmRhdGEpDQp0ZXN0DQpgYGANClRoZSBtYXRyaXggd2UgcmVjZWl2ZWQgYXMgYW4gb3V0cHV0IGlzIHRoZSBzdW1tYXJ5IG9mIG91ciByYW5raW5nIGRhdGEuIEl0IHNob3dzIHRoYXQsIGZvciBpbnN0YW5jZSwgdGhlIHByZWZlcmVuY2UgY29tYmluYXRpb24gIjIsMSwzLDQsNSIgcmVwZWF0cyAxMCB0aW1lcyBpbiB0aGUgZGF0YSBmcmFtZS4gTW9yZSBzcGVjaWZpY2FsbHksIGl0IG1lYW5zIHRoYXQgdGhlcmUgYXJlIDEwIHJlc3BvbmRlbnRzIHdobyBwcmVmZXIgdGhlIGl0ZW0gMigiQ2Fsb3JpZXMgYnVybmVkIikgdGhlIG1vc3QsIHRoZW4gdGhlIGl0ZW0gMSgiTWVhc3VyaW5nIHN0ZXBzIiksIGFuZCBzbyBvbi4NCg0KTm93IHdlIGNhbiBjYWxjdWxhdGUgdGhlIG1lYW4gcmFuayBmb3IgZWFjaCBmZWF0dXJlIGFuZCBjb25jbHVkZSB3aGljaCBmZWF0dXJlIGlzIHRoZSBtb3N0IGltcG9ydGFudCB0byBvdXIgcmVzcG9uZGVudHM6DQpgYGB7cn0NCiMgTWVhbiByYW5rIG9mIGVhY2ggZml0bmVzcyB0cmFja2VyIGZlYXR1cmUNCmRlc3RhdCh0ZXN0KSRtZWFuLnJhbmsNCmBgYA0KQXMgd2UgY2FuIG9ic2VydmUgZnJvbSB0aGUgb3V0cHV0LCB0aGUgaXRlbSAxKCJNZWFzdXJpbmcgc3RlcHMiKSBzaG93cyB0aGUgYmVzdCBtZWFuIHJhbmsgYW1vbmcgYWxsIGl0ZW1zLiBUaGVyZWZvcmUsIHdlIGNhbiBhc3N1bWUgdGhhdCB0aGUgIk1lYXN1cmluZyBzdGVwcyIgaXMgbW9zdCBpbXBvcnRhbnQgZm9yIG91ciByZXNwb25kZW50cy4gSG93ZXZlciwgaW4gb3JkZXIgdG8gc3RhdGlzdGljYWxseSBwcm92ZSBpdCBhbmQgYmVjb21lIHN1cmUgdGhhdCB0aGlzIGlzIG5vdCBqdXN0IGJ5IG1lcmUgY2hhbmNlLCB3ZSBjYW4gY29uZHVjdCAqKkZyaWVkbWFuIHJhbmsgc3VtIHRlc3QqKi4NCg0KRnJpZWRtYW4gcmFuayBzdW0gdGVzdCBpcyB1c2VkIHRvIGlkZW50aWZ5IHdoZXRoZXIgdGhlcmUgYXJlIGFueSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGRpc3RyaWJ1dGlvbnMgb2YgMyBvciBtb3JlIHBhaXJlZCBncm91cHMuIEl0IGlzIHVzZWQgd2hlbiB0aGUgbm9ybWFsaXR5IGFzc3VtcHRpb25zIGZvciB1c2luZyBvbmUtd2F5IHJlcGVhdGVkIG1lYXN1cmVzIEFOT1ZBIGFyZSBub3QgbWV0LiBBbm90aGVyIGNhc2Ugd2hlbiBGcmllZG1hbiByYW5rIHJ1bSB0ZXN0IGlzIHVzZWQgaXMgd2hlbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGlzIG1lYXN1cmVkIG9uIGFuIG9yZGluYWwgc2NhbGUsIGFzIGluIG91ciBjYXNlLg0KDQpCZWZvcmUgd2UgY29uZHVjdCB0aGUgRnJpZWRtYW4gcmFuayBzdW0gdGVzdCwgd2Ugd2lsbCB2aXN1YWxpc2Ugb3VyIGRhdGE6DQpgYGB7cn0NCiMgUHJlcGFyaW5nIGRhdGEgZnJhbWUgZm9yIEZyaWVkbWFuIHJhbmsgc3VtIHRlc3QNCmxpYnJhcnkocmVzaGFwZTIpDQpsaWJyYXJ5KGdncHVicikNCmxpYnJhcnkocnN0YXRpeCkNCmxpYnJhcnkoZ2dzdGF0c3Bsb3QpDQoNCnJhbmsuZGF0YS5sb25nIDwtIG1lbHQocmFuay5kYXRhLHZhbHVlLm5hbWUgPSAiUmFuayIsdmFyaWFibGUubmFtZSA9ICJGZWF0dXJlIikNCiMgV2UgaGF2ZSBqdXN0IHR1cm5lZCBvdXIgZGF0YSBmcmFtZSBmcm9tIHRoZSB3aWRlIGZvcm1hdCB0byB0aGUgbG9uZyBmb3JtYXQgYnkgdXNpbmcgZnVuY3Rpb24gbWVsdCgpLiBJZiB3ZSB0YWtlIGEgbG9vayBhdCBoZWFkIGFuZCB0YWlsIG9mIG91ciBuZXcgZGF0YSBmcmFtZSwgd2UgY2FuIHNlZSB0aGF0IGl0IGNvbnRhaW5zIGp1c3QgdHdvIGNvbHVtbnMsICJSYW5rIiBhbmQgIkZlYXR1cmUiLg0KdGFpbChyYW5rLmRhdGEubG9uZykNCmhlYWQocmFuay5kYXRhLmxvbmcpDQoNCiMgUXVpY2sgdmlzdWFsaXNhdGlvbg0KcCA8LSBnZ2JveHBsb3QocmFuay5kYXRhLmxvbmcsIHggPSAiRmVhdHVyZSIsIHkgPSAiUmFuayIsIGFkZCA9ICJqaXR0ZXIiLHRpdGxlID0gIldoYXQgZmVhdHVyZXMgYXJlIGltcG9ydGFudCB0byB5b3Ugd2hlbiBldnVhbHRpbmcgZml0bmVzcyB0cmFja2Vycz8iKQ0KZ2dwbG90bHkocCkNCg0KIyBBZHZhbmNlZCB2aXN1YWxpc2F0aW9uDQpnZ3N0YXRzcGxvdDo6Z2d3aXRoaW5zdGF0cygNCiAgZGF0YSA9IHJhbmsuZGF0YS5sb25nLA0KICB4ID0gRmVhdHVyZSwNCiAgeSA9IFJhbmssDQogIHR5cGUgPSAibnAiLA0KICBwYWlyd2lzZS5jb21wYXJpc29ucyA9IFRSVUUsICMgc2hvdyBwYWlyd2lzZSBjb21wYXJpc29uIHRlc3QgcmVzdWx0cw0KICB0aXRsZSA9ICJXaGF0IGZlYXR1cmVzIGFyZSBpbXBvcnRhbnQgdG8geW91IHdoZW4gZXZ1YWx0aW5nIGZpdG5lc3MgdHJhY2tlcnM/IikNCmBgYA0KDQpBbHJlYWR5IGZyb20gdGhlIGFkdmFuY2VkIHZpc3VhbGlzYXRpb24sIHRoYXQgaW5jbHVkZXMgRnJpZWRtYW4gcmFuayBzdW0gdGVzdCBhbmQgcGFpcndpc2UgY29tcGFyaXNvbiwgd2UgY2FuIGhhdmUgYW4gaW5zaWdodCBpbiBzaWduaWZpY2FuY2Ugb2YgZGlmZmVyZW5jZXMgYW1vbmcgZmVhdHVyZXMuICANCg0KYGBge3J9DQojIEZyaWVkbWFuIHRlc3QgDQpmcmllZG1hbi50ZXN0KGFzLm1hdHJpeChyYW5rLmRhdGEpKQ0KYGBgDQoNCkZyaWVkbWFuIHJhbmsgc3VtIHRlc3QgaGFzIGEgcC12YWx1ZSBsb3dlciB0aGFuIDAuMDUsIHNvIHdlIGNhbiBjb25jbHVkZSB0aGF0IGhlcmUgYXJlIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGJldHdlZW4gYXQgbGVhc3QgdHdvIGZlYXR1cmVzICh3aGF0IHdlIGhhdmUgYWxyZWFkeSBzZWVuIGluIG91ciB2aXN1YWxpc2F0aW9uKS4gRXZlbiB0aG91Z2ggd2UgaGF2ZSBpZGVudGlmaWVkIGRpZmZlcmVuY2VzIGJldHdlZW4gcHJlZmVyZW5jZXMgdG93YXJkcyBmZWF0dXJlcyBpbiBvdXIgYWR2YW5jZWQgdmlzdWFsaXNhdGlvbiwgd2Ugd2lsbCBjb25kdWN0IGEgcG9zdCBob2MgdGVzdCBpbiBvcmRlciB0byBkZW1vbnN0cmF0ZSB0cmFkaXRpb25hbCB3YXkgb2YgY2FsY3VsYXRpbmcgcGFpcndpc2UgY29tcGFyaXNvbnMuDQoNCg0KYGBge3J9DQp3aWxjb3hfdGVzdChSYW5rIH4gRmVhdHVyZSwgcGFpcmVkID0gVFJVRSwgcC5hZGp1c3QubWV0aG9kID0gImJvbmZlcnJvbmkiLCBkYXRhID0gcmFuay5kYXRhLmxvbmcpDQpgYGANClRoZSBvdXRwdXQgdGFibGUgcHJvdmlkZXMgdXMgd2l0aCBwLXZhbHVlcyByZWZlcnJpbmcgdG8gc2lnbmlmaWNhbmNlIG9mIGRpZmZlcmVuY2UgaW4gbWVhbiByYW5rcyBvZiBlYWNoIHBhaXIuIEZvciBpbnN0YW5jZSwgdGhlIGZpcnN0IDQgcm93cyAgcHJvdmVzIHRoYXQgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIG1lYW4gcmFuayBvZiB0aGUgZmVhdHVyZSAiTWVhc3VyaW5nIHN0ZXBzIiBhbmQgZWFjaCBvZiB0aGUgcmVzdCBvZiBmZWF0dXJlcyBhcmUgc2lnbmlmaWNhbnQuIENvbnNlcXVlbnRseSwgd2UgY2FuIGNvbmNsdWRlIHRoYXQgdGhpcyBmZWF0dXJlIGlzIGJ5IGZhciB0aGUgbW9zdCBpbXBvcnRhbnQgYW1vbmcgb3VyIHJlc3BvbmRlbnRzLiANCg0KDQpBbm90aGVyIHF1ZXN0aW9uIHRoYXQgbWF5IGJlIGludGVyZXN0aW5nIHRvIGV4cGxvcmUgaXMgd2hldGhlciB0aGVyZSBhcmUgYW55IGNvbXBsZW1lbnRhcnkgZmVhdXRyZXMgPyBPciBmZWF0dXJlcyB3aGljaCBvdmVybGFwIGVhY2ggb3RoZXIgaW4gaXRzIGZ1bmNpb25hbGl0eT8gSW4gb3JkZXIgdG8gaGF2ZSBhIGxvb2sgYXQgdGhhdCwgd2UgY2FuIGludmVzdGlnYXRlIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHJhbmtzIGFzc2lnbmVkIHRvIGVhY2ggZmVhdHVyZS4NCmBgYHtyfQ0KI0NvcnJlbGF0aW9uIE1hdHJpeA0KY29yLm1hdHJpeDwtY29yKHJhbmsuZGF0YSwgbWV0aG9kPWMoJ3NwZWFybWFuJykpDQpjb3IubWF0cml4DQpgYGANCkF0IHRoZSBmaXJzdCBnbGFuY2Ugd2UgY2FuIG9ic2VydmUgYSBsb3Qgb2YgbmVnYXRpdmUgdmFsdWVzLCBtZWFuaW5nIHRoYXQgbWFueSBmZWF0dXJlcyBjb3JyZWxhdGUgbmVnYXRpdmVseSByZWxhdGl2ZSB0byBlYWNoIG90aGVyLiBJbiBvcmRlciB0byBtYWtlIHRoZSBpbnRlcnByZXRhdGlvbiBlYXNpZXIsIHdlIHdpbGwgdHJ5IHRvIHZpc3VhbGlzZSBjb3JyZWxhdGlvbnMgaW4gYSBmb3JtIG9mIGEgY29ycmVsYXRpb24gbWF0cml4Lg0KDQpgYGB7cn0NCmxpYnJhcnkoY29ycnBsb3QpDQpjb3JycGxvdChjb3IubWF0cml4LCBtZXRob2Q9ImNvbG9yIiwgdHlwZSA9ICJ1cHBlciIsIG9yZGVyID0gImhjbHVzdCIpDQpgYGANCg0KRnJvbSB0aGUgY29ycmVsYXRpb24gbWF0cml4IHdlIGNhbiBjb25maXJtIHRoYXQgYWxtb3N0IGFsbCBmZWF0dXJlcyBuZWdhdGl2ZWx5IGNvcnJlbGF0ZSB0byBlYWNoIG90aGVyLiBBbiBleGNlcHRpb24gaXMgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGZlYXR1cmUgIk1lYXN1cmluZyBzdGVwcyIgYW5kICJFeGVyY2lzZSB0cmFja2luZyIsIHdoaWNoIGNvcnJlbGF0ZXMgcG9zaXR2ZWx5LiBUaGlzIG1hdHJpeCBjYW4gYmUgdXNlZnVsIGZvciBkaWdnaW5nIGRlZXBlciBpbiByZWxhdGlvbnNoaXAgYmV0d2VlbiBwcmVmZXJlbmNlcyBmb3IgZmVhdHVyZXMuIEZvciBpbnN0YW5jZSwgd2UgY2FuIGFzc3VtZSB0aGF0IGZlYXR1cmUgIk1lYXN1cmluZyBzdGVwcyIgYW5kICJFeGVyY2lzZSB0cmFja2luZyIgY29ycmVsYXRlIHBvc2l0aXZlbHkgYmVjYXVzZSB1c2VycyBzZWUgdGhlbSBhcyBjb21wbGVtZW50YXJ5IGZlYXR1cmVzLiBNb3Jlb3ZlciwgaWYgd2Ugc2F5IHRoYXQgd2Fsa2luZyBpcyBhIHR5cGUgb2YgZXhlcmNpc2UgKGluIGNhc2Ugb2YgbG9uZ2VyIHdhbGtpbmcgcm91dGVzKSwgd2UgY2FuIGFzc3VtZSB0aGF0IHVzZXJzLCB3aG8gcmFua2VkICJFeGVyY2lzZSB0cmFja2luZyIgaGlnaCwgcmFua2VkICJNZWFzdXJpbmcgc3RlcHMiIGhpZ2ggYXMgd2VsbCwgYmVjYXVzZSB0aGV5IHBlcmNlaXZlIGl0IGFzIGFub3RoZXIgdHlwZSBvZiAiRXhlcmNpc2UgdHJhY2tpbmciLg0KDQojIyMgQ29uc3RhbnQgU3VtIHF1ZXN0aW9uDQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5hbGlnbj0nY2VudGVyJyxvdXQud2lkdGg9JzUwJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnY29uc3RhbnQtc3VtLXF1ZXN0aW9uLnBuZycpDQpgYGANCg0KSWYgeW91IHdpc2ggdG8gb2J0YWluIGluZm9ybWF0aW9uIGFib3V0IGhvdyBtdWNoIG9uZSBhdHRyaWJ1dGUgaXMgcHJlZmVycmVkIG92ZXIgYW5vdGhlciBvbmUsIHlvdSBtYXkgdXNlIGEgY29uc3RhbnQgc3VtIHNjYWxlLiBUaGUgdG90YWwgYm94IHNob3VsZCBhbHdheXMgYmUgZGlzcGxheWVkIGF0IHRoZSBib3R0b20gdG8gbWFrZSBpdCBlYXNpZXIgZm9yIHJlc3BvbmRlbnRzLkEgY29uc3RhbnQgc3VtIHF1ZXN0aW9uIHBlcm1pdHMgY29sbGVjdGlvbiBvZiByYXRpbyBkYXRhIHR5cGUuIFdpdGggZGF0YSBvYnRhaW5lZCB3ZSB3b3VsZCBiZSBhYmxlIHRvIGV4cHJlc3MgdGhlIHJlbGF0aXZlIGltcG9ydGFuY2Ugb2YgdGhlIG9wdGlvbnMuDQoNCmBgYHtyLCBlY2hvPUZBTFNFLHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcid9DQpjb25zdGFudC5zdW0gPC0gc3Vic2V0KHF1YWx0cmljcywgc2VsZWN0ID1jKCIgTG9jYXRpb24iLCIgUHJpY2UiLCIgQW1iaWVuY2UiLCIgQ3VzdG9tZXIgU2VydmljZSIpKQ0KY29uc3RhbnQuc3VtJGlkIDwtIHNlcSgxOm5yb3coY29uc3RhbnQuc3VtKSkNCmtuaXRyOjprYWJsZShjb25zdGFudC5zdW1bMTo2LF0sIGNhcHRpb24gPSAiQ29uc3RhbnQgU3VtIFF1ZXN0aW9uIikNCmBgYA0KDQojIyMjIERhdGEgdmlzdWFsaXNhdGlvbg0KDQpgYGB7cn0NCiMgQ29tcHV0ZSBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzDQpsaWJyYXJ5KHBhc3RlY3MpIA0KcmVzIDwtIHN0YXQuZGVzYyhjb25zdGFudC5zdW0pDQpyb3VuZChyZXNbLDE6NF0sMikNCmBgYA0KDQpgYGB7cixlcnJvcj1GQUxTRSx3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KIyBDcmVhdGlvbiBvZiB0aGUgbG9uZyB2ZXJzaW9uIG9mIGRhdGEgZnJhbWUNCmNvbnN0YW50LnN1bS5sb25nIDwtbWVsdChjb25zdGFudC5zdW0sIHZhcmlhYmxlLm5hbWUgPSJGYWN0b3IiICx2YWx1ZS5uYW1lID0gIlBvaW50cyIpDQpjb25zdGFudC5zdW0ubG9uZw0KIyBCb3hwbG90IGJhc2ljDQpjb25zdGFudC5zdW1bLC01XSAlPiUNCmJveHBsb3QoY29uc3RhbnQuc3VtLmxvbmckUG9pbnRzIH4gY29uc3RhbnQuc3VtLmxvbmckRmFjdG9yICwgY29sPXJnYigwLjMsMC41LDAuNCwwLjYpICwgeWxhYj0iUG9pbnRzIix4bGFiPSIiLCBtYWluPSAiV2hhdCBmYWN0b3JzIGRvIHlvdSBjb25zaWRlciB3aGVuIGNob29zaW5nIGEgcGxhY2UgdG8gZ28gZm9yIGEgZGlubmVyPyIpDQoNCiMgQm94cGxvdCBnZ3Bsb3QyDQpwPC1jb25zdGFudC5zdW0ubG9uZyAlPiUgDQogIGZpbHRlcihGYWN0b3IhPSJpZCIpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9RmFjdG9yLCB5PVBvaW50cywgZmlsbD0gRmFjdG9yKSkgKw0KICAgIGdlb21fYm94cGxvdCgpICArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKCJXaGF0IGZhY3RvcnMgZG8geW91IGNvbnNpZGVyIHdoZW4gY2hvb3NpbmcgYSBwbGFjZSB0byBnbyBmb3IgYSBkaW5uZXI/IikgKw0KICAgIHhsYWIoIiIpDQpnZ3Bsb3RseShwKQ0KYGBgDQoNCldpdGggdGhlIGRhdGEgY29sbGVjdGVkIHdlIGFyZSBhYmxlIHRvIGFuc3dlciB0aGUgcXVlc3Rpb246IHdoYXQgZmFjdG9yIGlzIHRoZSBtb3N0IGltcG9ydGFudCBmb3Igb3VyIHJlc3BvbmRlbnRzIHdoZW4gdGhleSBnbyBvdXQgZm9yIGEgZGlubmVyPw0KDQpgYGB7cn0NCmxpYnJhcnkocm9iQ29tcG9zaXRpb25zKQ0KY29uc3RTdW0oY29uc3RhbnQuc3VtLDEwMCkNCmBgYA0KDQpJbiBvcmRlciB0byBhbndzZXIgdGhpcyBxdWVzdGlvbiB3ZSBuZWVkIHRvIGNvbmR1Y3QgKiphIHJlcGVhdGVkIG1lYXN1cmVzIEFOT1ZBKiouDQpUaGlzIHR5cGUgb2YgQU5PVkEgaXMgdXNlZCBmb3IgYW5hbHl6aW5nIGRhdGEgd2hlcmUgdGhlIHNhbWUgc3ViamVjdHMgYXJlIG1lYXN1cmVkIG1vcmUgdGhhbiBvbmNlLiBJbiBvdXIgY2FzZSB3ZSBoYXZlIGV2ZXJ5IHJlc3BvbmRlbnQgbWVhc3VyZWQgb24gZWFjaCBvZiB0aGUgZmFjdG9ycyAobG9jYXRpb25zLCBwcmljZSwgYW1iaWVuY2UgYW5kIGN1c3RvbWVyIHNlcnZpY2UpLiBSZXBlYXRlZCBtZWFzdXJlcyBBTk9WQSBpcyBhbiBleHRlbnNpb24gb2YgdGhlIHBhaXJlZC1zYW1wbGVzIHQtdGVzdC4gVGhpcyB0ZXN0IGlzIGFsc28gcmVmZXJyZWQgdG8gYXMgYSB3aXRoaW4tc3ViamVjdHMgQU5PVkEuIEluIHRoZSB3aXRoaW4tc3ViamVjdCBleHBlcmltZW50YWwgZGVzaWduIHRoZSBzYW1lIGluZGl2aWR1YWxzIGFyZSBtZWFzdXJlZCBvbiB0aGUgc2FtZSBvdXRjb21lIHZhcmlhYmxlIHVuZGVyIGRpZmZlcmVudCB0aW1lIHBvaW50cyBvciBjb25kaXRpb25zLg0KDQpXZSBuZWVkIHRvIGNoZWNrIGFsbCBhc3N1bXB0aW9ucyB0aGF0IG5lZWQgdG8gYmUgZnVsZmlsbGVkIGluIG9yZGVyIHRvIGRlcGxveSB0aGlzIHR5cGUgb2YgQU5PVkEuIFRoZXJlIGFyZSB0aHJlZSBhc3N1bXB1dGlvbnMgdGhhdCBuZWVkIHRvIGNoZWNrLiBUaGUgZmlyc3QgdG8gY2hlY2sgdGhhdCBlYWNoIGxldmVsIG9mIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZSBpcyBhcHByb3hpbWF0ZWx5IG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBTaW5jZSB3ZSBoYXZlIG1vcmUgdGhhbiAzMCBvYnNlcnZhdGlvbnMgYXQgZWFjaCBsZXZlbCwgd2UgZG8gbm90IG5lZWQgdG8gcHJvY2VlZCBmdXJ0aGVyIGR1ZSB0byB0aGUgY2VudHJhbCBsaW1pdCB0aGVvcmVtLiBTZWNvbmQgYXNzdW1wdGlvbiByZWZlcnJzIHRvIGV4dHJlbWUgb3V0bGllcnMuIExldCdzIGhhdmUgYSBsb29rIGF0IHBvdGVudGlhbCBvdXRsaWVyczoNCmBgYHtyfQ0KIyBPdXRsaWVycw0KY29uc3RhbnQuc3VtLmxvbmcgJT4lIA0KICBncm91cF9ieShGYWN0b3IpICU+JQ0KICBpZGVudGlmeV9vdXRsaWVycyhQb2ludHMpDQpgYGANCg0KQXMgd2UgY2Fubm90IGlkZW50aWZ5IGFueSBleHRyZW1lIG91dGxpZXJzLCB3ZSBjYW4gcHJvY2VlZCB3aXRoIGRlcGxveWluZyByZXBlYXRlZCBtZWFzdXJlcyBBTk9WQS4NCg0KYGBge3J9DQojIEZvcm1hdHRpbmcgZGF0YSANCmNvbnN0YW50LnN1bS5hb3YgPC0gZ2F0aGVyKGNvbnN0YW50LnN1bSwga2V5ID0gIkZhY3RvciIsIHZhbHVlID0gIlBvaW50cyIsIGAgTG9jYXRpb25gLGAgUHJpY2VgLGAgQW1iaWVuY2VgLGAgQ3VzdG9tZXIgU2VydmljZWApDQoNCiMgT25lLXdheSByZXBlYXRlZCBtZWFzdXJlcyBBTk9WQSAgDQpyZXMuYW92IDwtIGFub3ZhX3Rlc3QoZGF0YSA9IGNvbnN0YW50LnN1bS5hb3YsIGR2ID0gUG9pbnRzLHdpZCA9IGlkICx3aXRoaW4gPSBGYWN0b3IpDQpnZXRfYW5vdmFfdGFibGUocmVzLmFvdikNCg0KIyBQb3N0IGhvYyB0ZXN0DQpwYWlyd2lzZS50LnRlc3QoY29uc3RhbnQuc3VtLmxvbmckUG9pbnRzLGNvbnN0YW50LnN1bS5sb25nJEZhY3RvciwgcGFpcmVkID0gVCwgcC5hZGp1c3QubWV0aG9kID0gImhvbG0iKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dzdGF0c3Bsb3Q6Omdnd2l0aGluc3RhdHMoDQogIGRhdGEgPSBjb25zdGFudC5zdW0ubG9uZyAlPiUgZmlsdGVyKEZhY3RvciE9ImlkIiksICMgZXhjbHVkaW5nICJpZCIgY29sdW1uIGZyb20gdGhlIGRhdGENCiAgeCA9IEZhY3RvciwNCiAgeSA9IFBvaW50cywNCiAgdHlwZSA9ICJwIiwNCiAgcGFpcndpc2UuY29tcGFyaXNvbnMgPSBUUlVFLCAjIHNob3cgcGFpcndpc2UgY29tcGFyaXNvbiB0ZXN0IHJlc3VsdHMNCiAgdGl0bGUgPSAiV2hhdCBmYWN0b3JzIGRvIHlvdSBjb25zaWRlciB3aGVuIGNob29zaW5nIGEgcGxhY2UgdG8gZ28gZm9yIGEgZGlubmVyPyIpDQpgYGANCg0KIyMjIFRleHQgb3IgbnVtYmVyIGVudHJ5IHF1ZXN0aW9uDQoNCmBgYHtyLGVjaG89RkFMU0V9DQpzZXQuc2VlZCgxMjM0NTY3KQ0KcXVhbHRyaWNzJGAgV2lsbGluZ25lc3MtdG8tcGF5IChpbiBFVVIpYDwtIGFicyhhcy5pbnRlZ2VyKHJub3JtKG4gPSAxMTcsbWVhbj0yMyxzZD00MCkpKQ0KcXVhbHRyaWNzJGAgQ3VzdG9tZXIgU2VydmljZWAgPC0gYWJzKGFzLmludGVnZXIocnVuaWYobj0xMTcsbWluPTAsbWF4ID0gMTAwKSkpDQpgYGANCg0KDQpBIHRleHQgb3IgbnVtYmVyIGVudHJ5IHF1ZXN0aW9uIGlzIGEgcmVjb21tZW5kZWQgdHlwZSBvZiBxdWVzdGlvbiBpZiB5b3UgYXJlIGludGVyZXN0ZWQgaW4gb2J0YWluaW5nIHJhdGlvIGRhdGEgdHlwZS4gV2Ugd2lsbCB1c2UgdGhpcyB0eXBlIG9mIHF1ZXN0aW9uIHRvZ2V0aGVyIHdpdGggYSBjb25zdGFudCBzdW0gcXVlc3Rpb24gdHlwZSB0byBjb2xsZWN0IGRhdGEgdGhhdCBjYW4gYmUgYW5hbHlzZWQgd2l0aCByZWdyZXNzaW9uIGFuYWx5c2lzLiBOb3RlIHRoYXQgaW4gdGhpcyBjYXNlIHdlIHRyZWF0IGNvbnN0YW50IHN1bSBkYXRhIGFzIHJhdGlvIGRhdGEgYW5kIHRoZXJlZm9yZSBhc3N1bWUgdGhhdCAwIG1lYW5zIGNvbXBsZXRlIGFic2VuY2UuICANCg0KDQpIZXJlIGlzIGEgZ2xpbXBzZSBpbiBhbnN3ZXJzIG9uIGhvdyBpbXBvcnRhbnQgaXMgZWFjaCBmYWN0b3IgdG8gb3VyIHJlc3BvbmRlbnRzIHdoZW4gaXQgY29tZXMgdG8gZGlubmluZyBvdXRzaWRlOg0KYGBge3IsIGVjaG89IEZBTFNFfQ0Ka25pdHI6OmthYmxlKHF1YWx0cmljc1sxOjYsYygiIExvY2F0aW9uIiwiIFByaWNlIiwiIEFtYmllbmNlIiwiIEN1c3RvbWVyIFNlcnZpY2UiKV0sIGNhcHRpb24gPSAiQ29uc3RhbnQgc3VtIHF1ZXN0aW9uIikNCmBgYA0KDQpXZSBhc2tlZCBvdXIgcmVzcG9uZGVudHMgaG93IG11Y2ggYXJlIHRoZXkgd2lsbGluZyB0byBzcGVuZCBvbiBkaW5uZXIgb24gYXZlcmFnZTogDQpgYGB7ciwgZWNobz1GQUxTRX0NCmtuaXRyOjprYWJsZShoZWFkKHF1YWx0cmljcyRgIFdpbGxpbmduZXNzLXRvLXBheSAoaW4gRVVSKWApKQ0KYGBgDQoNCg0KSW4gb3JkZXIgdG8gaGFuZGxlIGRhdGEgZWFzaWVyLCB3ZSB3aWxsIGNyZWF0ZSBhIG5ldyBkYXRhIGZyYW1lOg0KYGBge3J9DQpkaW5uZXIgPC0gc3Vic2V0KHF1YWx0cmljcywgc2VsZWN0ID0gYygiIExvY2F0aW9uIiwiIFByaWNlIiwiIEFtYmllbmNlIiwiIEN1c3RvbWVyIFNlcnZpY2UiLCAiIFdpbGxpbmduZXNzLXRvLXBheSAoaW4gRVVSKSIpKQ0Ka25pdHI6OmthYmxlKGhlYWQoZGlubmVyKSkNCmBgYA0KQmVmb3JlIHdlIGNvbmR1Y3QgYSBsaW5lYXIgcmVncmVzc2lvbiBhbmFseXNpcywgd2UgbmVlZCB0byB0YWtlIGEgbG9vayBhdCBjb3JyZWxhdGlvbiBtYXRyaXg6ICANCg0KYGBge3J9DQpjb3JyZWxhdGlvbiA8LWNvcihkaW5uZXIsIG1ldGhvZD1jKCdwZWFyc29uJykpDQpjb3JyZWxhdGlvbg0KYGBgDQpGcm9tIG91ciBkYXRhIHdlIHNlZSwgZm9yIGluc3RhbmNlLCB0aGF0IHNvbWUgbmVnYXRpdmUgY29ycmVsYXRpb24gYmV0d2VlbiB3aWxsaW5nbmVzcyB0byBwYXkgYW5kIGltcG9ydGFuY2Ugb2YgYW1iaWVuY2UgYXMgd2VsbCBhcyBzb21lIHBvc2l0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gaW1wb3J0YW5jZSBvZiBjdXN0b21lciBzZXJ2aWNlIGFuZCB3aWxpbmduZXNzLXRvLXBheS4gTGV0IHVzIG9ic2VydmUgZGVzY3JpcHRpdmUgc3RhdGlzdGljcyBhcyB3ZWxsOiAgDQpgYGB7cn0NCnBzeWNoOjpkZXNjcmliZShkaW5uZXIpDQpgYGANCg0KV2Ugc2VlIHRoYXQgZGlmZmVyZW5jZSBiZXR3ZWVuIG1lYW4gYW5kIG1lZGlhbiBkb2VzIG5vdCBzdWdnZXN0IChhdCB0aGUgZmlyc3Qgc2lnaHQpIGdyZWF0IGVmZmVjdCBvZiBvdXRsaWVycy4NCkxldCB1cyBub3cgZG8gbGluZWFyIHJlZ3Jlc3Npb24gYW5hbHlzaXM6DQpgYGB7cn0NCm1sci5kaW5uZXIgPC0gbG0oYCBXaWxsaW5nbmVzcy10by1wYXkgKGluIEVVUilgIH4gYCBMb2NhdGlvbmAgKyBgIFByaWNlYCArIGAgQW1iaWVuY2VgK2AgQ3VzdG9tZXIgU2VydmljZWAsIGRhdGEgPSBkaW5uZXIpDQpzdW1tYXJ5KG1sci5kaW5uZXIpDQpgYGANCmBgYHtyLCBlY2hvPUZBTFNFfQ0KY29lZmYgPC0gc3VtbWFyeShtbHIuZGlubmVyKQ0KY29lZmYkY29lZmZpY2llbnRzWzQsMV0NCmBgYA0KDQpPdXQgb2YgYWxsIGZhY3RvcnMgb2YgaW1wb3J0YW5jZSB3aGVuIGRpbm5pbmcgb3V0LCB0aGUgb25seSBvbmUgdGhhdCBzdWdnZXN0cyBzaWduaWZpY2FuY2UgYXQgMC4wNSBsZXZlbCBvZiBzaWduaWZpY2FuY2UgaXMgYW1iaWVuY2UuIEZyb20gdGhlIHN1bW1hcnkgd2UgY2FuIGNvbmNsdWRlIHRoYXQgaW5jcmVhc2UgaW4gaW1wb3J0YW5jZSBvZiBhbWJpZW5jZSBieSAxIHBvaW50LCBsZWFkcyB0byBkZWNyZWFzZSBpbiB3aWxsaW5nbmVzcyB0byBwYXkgYnkgYHIgY29lZmYkY29lZmZpY2llbnRzWzQsMV1gLg0KDQpgYGB7cn0NCmNvbmZpbnQobWxyLmRpbm5lcikNCmBgYA0KDQpGcm9tIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLCBXZSBjYW4gY29uY2x1ZGUgdGhhdCB3aGVuIHdlIGRvIG5vdCBjb25zaWRlciBhbnkgb2YgZ2l2ZW4gZmFjdG9ycyAobG9jYXRpb24sIHByaWNlLCBhbWJpZW5jZSBhbmQgY3VzdG9tZXIgc2VydmljZSksIHdpbGxpbmduZXNzIHRvIHBheSAgd2lsbCBiZSBzb21ld2hlcmUgYmV0d2VlbiBgciBjb25maW50KG1sci5kaW5uZXIpWzEsMV1gRVVSIGFuZCBgciBjb25maW50KG1sci5kaW5uZXIpWzEsMl1gRVVSLiBCZXNpZGVzIHRoYXQsIGZvciBlYWNoIGluY3JlYXNlIGluIGltcG9ydGFuY2Ugb2YgZGlubmVyIGFtYmllbmNlIGJ5IG9uZSBwb2ludCwgdGhlcmUgd2lsbCBiZSBhbiBhdmVyYWdlIGRlY3JlYXNlIG9mIHdpbGxpbmduZXNzIHRvIHBheSBiZXR3ZWVuIGByIGNvbmZpbnQobWxyLmRpbm5lcilbNCwxXWAgYW5kIGByIGNvbmZpbnQobWxyLmRpbm5lcilbNCwyXWAuDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRX0NCmdnY29lZnN0YXRzKHggPSBtbHIuZGlubmVyLA0KICAgICAgICAgICAgdGl0bGUgPSAiV2lsbGluZ25lc3MgdG8gcGF5IHByZWRpY3RlZCBieSBpbXBvcnRhbmNlIG9mIGZhY3RvcnMiKQ0KYGBgDQoNCg0KYGBge3J9DQojIE91dGxpZXJzDQptbHIuZGlubmVyJHN0dWRfcmVzaWQgPC0gcnN0dWRlbnQobWxyLmRpbm5lcikNCmhlYWQobWxyLmRpbm5lcikNCmBgYA0KDQoNCmBgYHtyfQ0Kb3V0bGllcl92YWx1ZXMgPC0gYm94cGxvdC5zdGF0cyhtbHIuZGlubmVyJHJlc2lkdWFscykkb3V0ICAjIG91dGxpZXIgdmFsdWVzLg0Kb3V0bGllcl92YWx1ZXMNCmJveHBsb3QobWxyLmRpbm5lciRyZXNpZHVhbHMsIG1haW49IldpbGxpbmduZXMgdG8gcGF5IiwgYm94d2V4PTAuMSkNCmBgYA0KDQo=